mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 16:07:30 +03:00 
			
		
		
		
	Merge branch 'main' into include-dir-type-confusion
This commit is contained in:
		
						commit
						6fce7d6ed4
					
				|  | @ -43,7 +43,7 @@ if [[ $(uname) != CYGWIN* ]]; then | |||
|     # PyQt6 doesn't support PyPy3 | ||||
|     if [[ $GHA_PYTHON_VERSION == 3.* ]]; then | ||||
|         sudo apt-get -qq install libegl1 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxkbcommon-x11-0 | ||||
|         python3 -m pip install pyqt6 | ||||
|         python3 -m pip install pyqt6 PyQt6-Qt6!=6.5.0 | ||||
|     fi | ||||
| 
 | ||||
|     # webp | ||||
|  |  | |||
							
								
								
									
										1
									
								
								.github/workflows/test-cygwin.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/test-cygwin.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -67,7 +67,6 @@ jobs: | |||
|             python3${{ matrix.python-minor-version }}-numpy | ||||
|             python3${{ matrix.python-minor-version }}-sip | ||||
|             python3${{ matrix.python-minor-version }}-tkinter | ||||
|             qt5-devel-tools | ||||
|             wget | ||||
|             xorg-server-extra | ||||
|             zlib-devel | ||||
|  |  | |||
|  | @ -5,6 +5,9 @@ Changelog (Pillow) | |||
| 10.0.0 (unreleased) | ||||
| ------------------- | ||||
| 
 | ||||
| - Remove deprecations for Pillow 10.0.0 #7059 | ||||
|   [hugovk, radarhere] | ||||
| 
 | ||||
| - Drop support for soon-EOL Python 3.7 #7058 | ||||
|   [hugovk, radarhere] | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							|  | @ -78,6 +78,7 @@ debug: | |||
| 
 | ||||
| .PHONY: release-test | ||||
| release-test: | ||||
| 	python3 Tests/check_release_notes.py | ||||
| 	python3 -m pip install -e .[tests] | ||||
| 	python3 selftest.py | ||||
| 	python3 -m pytest Tests | ||||
|  |  | |||
							
								
								
									
										6
									
								
								Tests/check_release_notes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Tests/check_release_notes.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| import sys | ||||
| from pathlib import Path | ||||
| 
 | ||||
| for rst in Path("docs/releasenotes").glob("[1-9]*.rst"): | ||||
|     if "TODO" in open(rst).read(): | ||||
|         sys.exit(f"Error: remove TODO from {rst}") | ||||
|  | @ -1,18 +0,0 @@ | |||
| import warnings | ||||
| 
 | ||||
| with warnings.catch_warnings(record=True) as w: | ||||
|     # Arrange: cause all warnings to always be triggered | ||||
|     warnings.simplefilter("always") | ||||
| 
 | ||||
|     # Act: trigger a warning with Qt5 | ||||
|     from PIL import ImageQt | ||||
| 
 | ||||
| 
 | ||||
| def test_deprecated(): | ||||
|     # Assert | ||||
|     if ImageQt.qt_version in ("5", "side2"): | ||||
|         assert len(w) == 1 | ||||
|         assert issubclass(w[0].category, DeprecationWarning) | ||||
|         assert "deprecated" in str(w[0].message) | ||||
|     else: | ||||
|         assert len(w) == 0 | ||||
|  | @ -655,13 +655,3 @@ def test_different_modes_in_later_frames(mode, tmp_path): | |||
|     im.save(test_file, save_all=True, append_images=[Image.new(mode, (1, 1))]) | ||||
|     with Image.open(test_file) as reloaded: | ||||
|         assert reloaded.mode == mode | ||||
| 
 | ||||
| 
 | ||||
| def test_constants_deprecation(): | ||||
|     for enum, prefix in { | ||||
|         PngImagePlugin.Disposal: "APNG_DISPOSE_", | ||||
|         PngImagePlugin.Blend: "APNG_BLEND_", | ||||
|     }.items(): | ||||
|         for name in enum.__members__: | ||||
|             with pytest.warns(DeprecationWarning): | ||||
|                 assert getattr(PngImagePlugin, prefix + name) == enum[name] | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import pytest | ||||
| 
 | ||||
| from PIL import BlpImagePlugin, Image | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import ( | ||||
|     assert_image_equal, | ||||
|  | @ -72,14 +72,3 @@ def test_crashes(test_file): | |||
|         with Image.open(f) as im: | ||||
|             with pytest.raises(OSError): | ||||
|                 im.load() | ||||
| 
 | ||||
| 
 | ||||
| def test_constants_deprecation(): | ||||
|     for enum, prefix in { | ||||
|         BlpImagePlugin.Format: "BLP_FORMAT_", | ||||
|         BlpImagePlugin.Encoding: "BLP_ENCODING_", | ||||
|         BlpImagePlugin.AlphaEncoding: "BLP_ALPHA_ENCODING_", | ||||
|     }.items(): | ||||
|         for name in enum.__members__: | ||||
|             with pytest.warns(DeprecationWarning): | ||||
|                 assert getattr(BlpImagePlugin, prefix + name) == enum[name] | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ from io import BytesIO | |||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from PIL import FitsImagePlugin, FitsStubImagePlugin, Image | ||||
| from PIL import FitsImagePlugin, Image | ||||
| 
 | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
|  | @ -48,39 +48,3 @@ def test_comment(): | |||
|     image_data = b"SIMPLE  =                    T / comment string" | ||||
|     with pytest.raises(OSError): | ||||
|         FitsImagePlugin.FitsImageFile(BytesIO(image_data)) | ||||
| 
 | ||||
| 
 | ||||
| def test_stub_deprecated(): | ||||
|     class Handler: | ||||
|         opened = False | ||||
|         loaded = False | ||||
| 
 | ||||
|         def open(self, im): | ||||
|             self.opened = True | ||||
| 
 | ||||
|         def load(self, im): | ||||
|             self.loaded = True | ||||
|             im.fp.close() | ||||
|             return Image.new("RGB", (1, 1)) | ||||
| 
 | ||||
|     handler = Handler() | ||||
|     with pytest.warns(DeprecationWarning): | ||||
|         FitsStubImagePlugin.register_handler(handler) | ||||
| 
 | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         assert im.format == "FITS" | ||||
|         assert im.size == (128, 128) | ||||
|         assert im.mode == "L" | ||||
| 
 | ||||
|         assert handler.opened | ||||
|         assert not handler.loaded | ||||
| 
 | ||||
|         im.load() | ||||
|         assert handler.loaded | ||||
| 
 | ||||
|     FitsStubImagePlugin._handler = None | ||||
|     Image.register_open( | ||||
|         FitsImagePlugin.FitsImageFile.format, | ||||
|         FitsImagePlugin.FitsImageFile, | ||||
|         FitsImagePlugin._accept, | ||||
|     ) | ||||
|  |  | |||
|  | @ -21,12 +21,3 @@ def test_invalid_file(): | |||
| 
 | ||||
|     with pytest.raises(SyntaxError): | ||||
|         FtexImagePlugin.FtexImageFile(invalid_file) | ||||
| 
 | ||||
| 
 | ||||
| def test_constants_deprecation(): | ||||
|     for enum, prefix in { | ||||
|         FtexImagePlugin.Format: "FORMAT_", | ||||
|     }.items(): | ||||
|         for name in enum.__members__: | ||||
|             with pytest.warns(DeprecationWarning): | ||||
|                 assert getattr(FtexImagePlugin, prefix + name) == enum[name] | ||||
|  |  | |||
|  | @ -636,12 +636,6 @@ class TestFileJpeg: | |||
|             assert max(im2.quantization[0]) <= 255 | ||||
|             assert max(im2.quantization[1]) <= 255 | ||||
| 
 | ||||
|     def test_convert_dict_qtables_deprecation(self): | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             qtable = {0: [1, 2, 3, 4]} | ||||
|             qtable2 = JpegImagePlugin.convert_dict_qtables(qtable) | ||||
|             assert qtable == qtable2 | ||||
| 
 | ||||
|     @pytest.mark.skipif(not djpeg_available(), reason="djpeg not available") | ||||
|     def test_load_djpeg(self): | ||||
|         with Image.open(TEST_FILE) as img: | ||||
|  |  | |||
|  | @ -929,25 +929,7 @@ class TestImage: | |||
|             im.apply_transparency() | ||||
|             assert im.palette.colors[(27, 35, 6, 214)] == 24 | ||||
| 
 | ||||
|     def test_categories_deprecation(self): | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             assert hopper().category == 0 | ||||
| 
 | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             assert Image.NORMAL == 0 | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             assert Image.SEQUENCE == 1 | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             assert Image.CONTAINER == 2 | ||||
| 
 | ||||
|     def test_constants(self): | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             assert Image.LINEAR == Image.Resampling.BILINEAR | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             assert Image.CUBIC == Image.Resampling.BICUBIC | ||||
|         with pytest.warns(DeprecationWarning): | ||||
|             assert Image.ANTIALIAS == Image.Resampling.LANCZOS | ||||
| 
 | ||||
|         for enum in ( | ||||
|             Image.Transpose, | ||||
|             Image.Transform, | ||||
|  |  | |||
|  | @ -1,7 +1,5 @@ | |||
| import pytest | ||||
| 
 | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| 
 | ||||
|  | @ -62,8 +60,3 @@ def test_f_mode(): | |||
|     im = hopper("F") | ||||
|     with pytest.raises(ValueError): | ||||
|         im.point(None) | ||||
| 
 | ||||
| 
 | ||||
| def test_coerce_e_deprecation(): | ||||
|     with pytest.warns(DeprecationWarning): | ||||
|         assert Image.coerce_e(2).data == 2 | ||||
|  |  | |||
|  | @ -617,16 +617,6 @@ def test_auxiliary_channels_isolated(): | |||
|                 assert_image_equal(test_image.convert(dst_format[2]), reference_image) | ||||
| 
 | ||||
| 
 | ||||
| def test_constants_deprecation(): | ||||
|     for enum, prefix in { | ||||
|         ImageCms.Intent: "INTENT_", | ||||
|         ImageCms.Direction: "DIRECTION_", | ||||
|     }.items(): | ||||
|         for name in enum.__members__: | ||||
|             with pytest.warns(DeprecationWarning): | ||||
|                 assert getattr(ImageCms, prefix + name) == enum[name] | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX")) | ||||
| def test_rgb_lab(mode): | ||||
|     im = Image.new(mode, (1, 1)) | ||||
|  |  | |||
|  | @ -1083,14 +1083,6 @@ def test_woff2(layout_engine): | |||
|     assert_image_similar_tofile(im, "Tests/images/test_woff2.png", 5) | ||||
| 
 | ||||
| 
 | ||||
| def test_fill_deprecation(font): | ||||
|     with pytest.warns(DeprecationWarning): | ||||
|         font.getmask2("Hello world", fill=Image.core.fill) | ||||
|     with pytest.warns(DeprecationWarning): | ||||
|         with pytest.raises(TypeError): | ||||
|             font.getmask2("Hello world", fill=None) | ||||
| 
 | ||||
| 
 | ||||
| def test_render_mono_size(): | ||||
|     # issue 4177 | ||||
| 
 | ||||
|  | @ -1130,12 +1122,3 @@ def test_raqm_missing_warning(monkeypatch): | |||
|         "Raqm layout was requested, but Raqm is not available. " | ||||
|         "Falling back to basic layout." | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def test_constants_deprecation(): | ||||
|     for enum, prefix in { | ||||
|         ImageFont.Layout: "LAYOUT_", | ||||
|     }.items(): | ||||
|         for name in enum.__members__: | ||||
|             with pytest.warns(DeprecationWarning): | ||||
|                 assert getattr(ImageFont, prefix + name) == enum[name] | ||||
|  |  | |||
|  | @ -9,10 +9,6 @@ def test_sanity(): | |||
|     palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3) | ||||
|     assert len(palette.colors) == 256 | ||||
| 
 | ||||
|     with pytest.warns(DeprecationWarning): | ||||
|         with pytest.raises(ValueError): | ||||
|             ImagePalette.ImagePalette("RGB", list(range(256)) * 3, 10) | ||||
| 
 | ||||
| 
 | ||||
| def test_reload(): | ||||
|     with Image.open("Tests/images/hopper.gif") as im: | ||||
|  |  | |||
|  | @ -2,13 +2,10 @@ import warnings | |||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from PIL import ImageQt | ||||
| 
 | ||||
| from .helper import assert_image_similar, hopper | ||||
| 
 | ||||
| with warnings.catch_warnings() as w: | ||||
|     warnings.simplefilter("ignore", category=DeprecationWarning) | ||||
|     from PIL import ImageQt | ||||
| 
 | ||||
| 
 | ||||
| pytestmark = pytest.mark.skipif( | ||||
|     not ImageQt.qt_is_installed, reason="Qt bindings are not installed" | ||||
| ) | ||||
|  | @ -26,10 +23,6 @@ def test_rgb(): | |||
|         from PyQt6.QtGui import qRgb | ||||
|     elif ImageQt.qt_version == "side6": | ||||
|         from PySide6.QtGui import qRgb | ||||
|     elif ImageQt.qt_version == "5": | ||||
|         from PyQt5.QtGui import qRgb | ||||
|     elif ImageQt.qt_version == "side2": | ||||
|         from PySide2.QtGui import qRgb | ||||
| 
 | ||||
|     assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255) | ||||
| 
 | ||||
|  |  | |||
|  | @ -89,20 +89,3 @@ def test_ipythonviewer(): | |||
| 
 | ||||
|     im = hopper() | ||||
|     assert test_viewer.show(im) == 1 | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif( | ||||
|     not on_ci() or is_win32(), | ||||
|     reason="Only run on CIs; hangs on Windows CIs", | ||||
| ) | ||||
| @pytest.mark.parametrize("viewer", ImageShow._viewers) | ||||
| def test_file_deprecated(tmp_path, viewer): | ||||
|     f = str(tmp_path / "temp.jpg") | ||||
|     hopper().save(f) | ||||
|     with pytest.warns(DeprecationWarning): | ||||
|         try: | ||||
|             viewer.show_file(file=f) | ||||
|         except NotImplementedError: | ||||
|             pass | ||||
|     with pytest.raises(TypeError): | ||||
|         viewer.show_file() | ||||
|  |  | |||
|  | @ -89,13 +89,6 @@ def test_photoimage_blank(mode): | |||
|     assert_image_equal(reloaded.convert(mode), im) | ||||
| 
 | ||||
| 
 | ||||
| def test_box_deprecation(): | ||||
|     im = hopper() | ||||
|     im_tk = ImageTk.PhotoImage(im) | ||||
|     with pytest.warns(DeprecationWarning): | ||||
|         im_tk.paste(im, (0, 0, 128, 128)) | ||||
| 
 | ||||
| 
 | ||||
| def test_bitmapimage(): | ||||
|     im = hopper("1") | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,10 +1,6 @@ | |||
| import warnings | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| with warnings.catch_warnings(): | ||||
|     warnings.simplefilter("ignore", category=DeprecationWarning) | ||||
|     from PIL import ImageQt | ||||
| from PIL import ImageQt | ||||
| 
 | ||||
| from .helper import assert_image_equal_tofile, assert_image_similar, hopper | ||||
| 
 | ||||
|  | @ -19,14 +15,6 @@ if ImageQt.qt_is_installed: | |||
|         from PySide6.QtCore import QPoint | ||||
|         from PySide6.QtGui import QImage, QPainter, QRegion | ||||
|         from PySide6.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget | ||||
|     elif ImageQt.qt_version == "5": | ||||
|         from PyQt5.QtCore import QPoint | ||||
|         from PyQt5.QtGui import QImage, QPainter, QRegion | ||||
|         from PyQt5.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget | ||||
|     elif ImageQt.qt_version == "side2": | ||||
|         from PySide2.QtCore import QPoint | ||||
|         from PySide2.QtGui import QImage, QPainter, QRegion | ||||
|         from PySide2.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget | ||||
| 
 | ||||
|     class Example(QWidget): | ||||
|         def __init__(self): | ||||
|  |  | |||
|  | @ -1,10 +1,6 @@ | |||
| import warnings | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| with warnings.catch_warnings(): | ||||
|     warnings.simplefilter("ignore", category=DeprecationWarning) | ||||
|     from PIL import ImageQt | ||||
| from PIL import ImageQt | ||||
| 
 | ||||
| from .helper import assert_image_equal, assert_image_equal_tofile, hopper | ||||
| 
 | ||||
|  | @ -32,7 +28,7 @@ def test_sanity(mode, tmp_path): | |||
|         assert_image_equal(rt, src) | ||||
| 
 | ||||
|     if mode == "1": | ||||
|         # BW appears to not save correctly on QT5 | ||||
|         # BW appears to not save correctly on Qt | ||||
|         # kicks out errors on console: | ||||
|         #     libpng warning: Invalid color type/bit depth combination | ||||
|         #                     in IHDR | ||||
|  |  | |||
|  | @ -12,150 +12,6 @@ Deprecated features | |||
| Below are features which are considered deprecated. Where appropriate, | ||||
| a ``DeprecationWarning`` is issued. | ||||
| 
 | ||||
| Tk/Tcl 8.4 | ||||
| ~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.2.0 | ||||
| 
 | ||||
| Support for Tk/Tcl 8.4 is deprecated and will be removed in Pillow 10.0.0 (2023-07-01), | ||||
| when Tk/Tcl 8.5 will be the minimum supported. | ||||
| 
 | ||||
| Categories | ||||
| ~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.2.0 | ||||
| 
 | ||||
| ``im.category`` is deprecated and will be removed in Pillow 10.0.0 (2023-07-01), | ||||
| along with the related ``Image.NORMAL``, ``Image.SEQUENCE`` and | ||||
| ``Image.CONTAINER`` attributes. | ||||
| 
 | ||||
| To determine if an image has multiple frames or not, | ||||
| ``getattr(im, "is_animated", False)`` can be used instead. | ||||
| 
 | ||||
| JpegImagePlugin.convert_dict_qtables | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.3.0 | ||||
| 
 | ||||
| JPEG ``quantization`` is now automatically converted, but still returned as a | ||||
| dictionary. The :py:attr:`~PIL.JpegImagePlugin.convert_dict_qtables` method no longer | ||||
| performs any operations on the data given to it, has been deprecated and will be | ||||
| removed in Pillow 10.0.0 (2023-07-01). | ||||
| 
 | ||||
| ImagePalette size parameter | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.4.0 | ||||
| 
 | ||||
| The ``size`` parameter will be removed in Pillow 10.0.0 (2023-07-01). | ||||
| 
 | ||||
| Before Pillow 8.3.0, ``ImagePalette`` required palette data of particular lengths by | ||||
| default, and the size parameter could be used to override that. Pillow 8.3.0 removed | ||||
| the default required length, also removing the need for the size parameter. | ||||
| 
 | ||||
| ImageShow.Viewer.show_file file argument | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.1.0 | ||||
| 
 | ||||
| The ``file`` argument in :py:meth:`~PIL.ImageShow.Viewer.show_file()` has been | ||||
| deprecated and will be removed in Pillow 10.0.0 (2023-07-01). It has been replaced by | ||||
| ``path``. | ||||
| 
 | ||||
| In effect, ``viewer.show_file("test.jpg")`` will continue to work unchanged. | ||||
| ``viewer.show_file(file="test.jpg")`` will raise a deprecation warning, and suggest | ||||
| ``viewer.show_file(path="test.jpg")`` instead. | ||||
| 
 | ||||
| Constants | ||||
| ~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.1.0 | ||||
| 
 | ||||
| A number of constants have been deprecated and will be removed in Pillow 10.0.0 | ||||
| (2023-07-01). Instead, ``enum.IntEnum`` classes have been added. | ||||
| 
 | ||||
| .. note:: | ||||
| 
 | ||||
|     Additional ``Image`` constants were deprecated in Pillow 9.1.0, but that | ||||
|     was reversed in Pillow 9.4.0 and those constants will now remain available. | ||||
|     See :ref:`restored-image-constants` | ||||
| 
 | ||||
| =====================================================  ============================================================ | ||||
| Deprecated                                             Use instead | ||||
| =====================================================  ============================================================ | ||||
| ``Image.LINEAR``                                       ``Image.BILINEAR`` or ``Image.Resampling.BILINEAR`` | ||||
| ``Image.CUBIC``                                        ``Image.BICUBIC`` or ``Image.Resampling.BICUBIC`` | ||||
| ``Image.ANTIALIAS``                                    ``Image.LANCZOS`` or ``Image.Resampling.LANCZOS`` | ||||
| ``ImageCms.INTENT_PERCEPTUAL``                         ``ImageCms.Intent.PERCEPTUAL`` | ||||
| ``ImageCms.INTENT_RELATIVE_COLORMETRIC``               ``ImageCms.Intent.RELATIVE_COLORMETRIC`` | ||||
| ``ImageCms.INTENT_SATURATION``                         ``ImageCms.Intent.SATURATION`` | ||||
| ``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC``              ``ImageCms.Intent.ABSOLUTE_COLORIMETRIC`` | ||||
| ``ImageCms.DIRECTION_INPUT``                           ``ImageCms.Direction.INPUT`` | ||||
| ``ImageCms.DIRECTION_OUTPUT``                          ``ImageCms.Direction.OUTPUT`` | ||||
| ``ImageCms.DIRECTION_PROOF``                           ``ImageCms.Direction.PROOF`` | ||||
| ``ImageFont.LAYOUT_BASIC``                             ``ImageFont.Layout.BASIC`` | ||||
| ``ImageFont.LAYOUT_RAQM``                              ``ImageFont.Layout.RAQM`` | ||||
| ``BlpImagePlugin.BLP_FORMAT_JPEG``                     ``BlpImagePlugin.Format.JPEG`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED``           ``BlpImagePlugin.Encoding.UNCOMPRESSED`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_DXT``                    ``BlpImagePlugin.Encoding.DXT`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED_RAW_RGBA``  ``BlpImagePlugin.Encoding.UNCOMPRESSED_RAW_RGBA`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT1``             ``BlpImagePlugin.AlphaEncoding.DXT1`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT3``             ``BlpImagePlugin.AlphaEncoding.DXT3`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT5``             ``BlpImagePlugin.AlphaEncoding.DXT5`` | ||||
| ``FtexImagePlugin.FORMAT_DXT1``                        ``FtexImagePlugin.Format.DXT1`` | ||||
| ``FtexImagePlugin.FORMAT_UNCOMPRESSED``                ``FtexImagePlugin.Format.UNCOMPRESSED`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_NONE``                ``PngImagePlugin.Disposal.OP_NONE`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_BACKGROUND``          ``PngImagePlugin.Disposal.OP_BACKGROUND`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_PREVIOUS``            ``PngImagePlugin.Disposal.OP_PREVIOUS`` | ||||
| ``PngImagePlugin.APNG_BLEND_OP_SOURCE``                ``PngImagePlugin.Blend.OP_SOURCE`` | ||||
| ``PngImagePlugin.APNG_BLEND_OP_OVER``                  ``PngImagePlugin.Blend.OP_OVER`` | ||||
| =====================================================  ============================================================ | ||||
| 
 | ||||
| FitsStubImagePlugin | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.1.0 | ||||
| 
 | ||||
| The stub image plugin ``FitsStubImagePlugin`` has been deprecated and will be removed in | ||||
| Pillow 10.0.0 (2023-07-01). FITS images can be read without a handler through | ||||
| :mod:`~PIL.FitsImagePlugin` instead. | ||||
| 
 | ||||
| FreeTypeFont.getmask2 fill parameter | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| 
 | ||||
| The undocumented ``fill`` parameter of :py:meth:`.FreeTypeFont.getmask2` has been | ||||
| deprecated and will be removed in Pillow 10 (2023-07-01). | ||||
| 
 | ||||
| PhotoImage.paste box parameter | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| 
 | ||||
| The ``box`` parameter is unused. It will be removed in Pillow 10.0.0 (2023-07-01). | ||||
| 
 | ||||
| PyQt5 and PySide2 | ||||
| ~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| 
 | ||||
| `Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for | ||||
| open-source users (and will reach EOL on 2023-12-08 for commercial licence holders). | ||||
| 
 | ||||
| Support for PyQt5 and PySide2 has been deprecated from ``ImageQt`` and will be removed | ||||
| in Pillow 10 (2023-07-01). Upgrade to | ||||
| `PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or | ||||
| `PySide6 <https://doc.qt.io/qtforpython/>`_ instead. | ||||
| 
 | ||||
| Image.coerce_e | ||||
| ~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| 
 | ||||
| This undocumented method has been deprecated and will be removed in Pillow 10 | ||||
| (2023-07-01). | ||||
| 
 | ||||
| .. _Font size and offset methods: | ||||
| 
 | ||||
| Font size and offset methods | ||||
|  | @ -223,6 +79,149 @@ Removed features | |||
| Deprecated features are only removed in major releases after an appropriate | ||||
| period of deprecation has passed. | ||||
| 
 | ||||
| Tk/Tcl 8.4 | ||||
| ~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.2.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| Support for Tk/Tcl 8.4 was removed in Pillow 10.0.0 (2023-07-01). | ||||
| 
 | ||||
| Categories | ||||
| ~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.2.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| ``im.category`` was removed along with the related ``Image.NORMAL``, | ||||
| ``Image.SEQUENCE`` and ``Image.CONTAINER`` attributes. | ||||
| 
 | ||||
| To determine if an image has multiple frames or not, | ||||
| ``getattr(im, "is_animated", False)`` can be used instead. | ||||
| 
 | ||||
| JpegImagePlugin.convert_dict_qtables | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.3.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| Since deprecation in Pillow 8.3.0, the ``convert_dict_qtables`` method no longer | ||||
| performed any operations on the data given to it, and has been removed. | ||||
| 
 | ||||
| ImagePalette size parameter | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 8.4.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| Before Pillow 8.3.0, ``ImagePalette`` required palette data of particular lengths by | ||||
| default, and the ``size`` parameter could be used to override that. Pillow 8.3.0 | ||||
| removed the default required length, also removing the need for the ``size`` parameter. | ||||
| 
 | ||||
| ImageShow.Viewer.show_file file argument | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.1.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| The ``file`` argument in :py:meth:`~PIL.ImageShow.Viewer.show_file()` has been | ||||
| removed and replaced by ``path``. | ||||
| 
 | ||||
| In effect, ``viewer.show_file("test.jpg")`` will continue to work unchanged. | ||||
| 
 | ||||
| Constants | ||||
| ~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.1.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| A number of constants have been removed. | ||||
| Instead, ``enum.IntEnum`` classes have been added. | ||||
| 
 | ||||
| .. note:: | ||||
| 
 | ||||
|     Additional ``Image`` constants were deprecated in Pillow 9.1.0, but that | ||||
|     was reversed in Pillow 9.4.0 and those constants will now remain available. | ||||
|     See :ref:`restored-image-constants` | ||||
| 
 | ||||
| =====================================================  ============================================================ | ||||
| Removed                                                Use instead | ||||
| =====================================================  ============================================================ | ||||
| ``Image.LINEAR``                                       ``Image.BILINEAR`` or ``Image.Resampling.BILINEAR`` | ||||
| ``Image.CUBIC``                                        ``Image.BICUBIC`` or ``Image.Resampling.BICUBIC`` | ||||
| ``Image.ANTIALIAS``                                    ``Image.LANCZOS`` or ``Image.Resampling.LANCZOS`` | ||||
| ``ImageCms.INTENT_PERCEPTUAL``                         ``ImageCms.Intent.PERCEPTUAL`` | ||||
| ``ImageCms.INTENT_RELATIVE_COLORMETRIC``               ``ImageCms.Intent.RELATIVE_COLORMETRIC`` | ||||
| ``ImageCms.INTENT_SATURATION``                         ``ImageCms.Intent.SATURATION`` | ||||
| ``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC``              ``ImageCms.Intent.ABSOLUTE_COLORIMETRIC`` | ||||
| ``ImageCms.DIRECTION_INPUT``                           ``ImageCms.Direction.INPUT`` | ||||
| ``ImageCms.DIRECTION_OUTPUT``                          ``ImageCms.Direction.OUTPUT`` | ||||
| ``ImageCms.DIRECTION_PROOF``                           ``ImageCms.Direction.PROOF`` | ||||
| ``ImageFont.LAYOUT_BASIC``                             ``ImageFont.Layout.BASIC`` | ||||
| ``ImageFont.LAYOUT_RAQM``                              ``ImageFont.Layout.RAQM`` | ||||
| ``BlpImagePlugin.BLP_FORMAT_JPEG``                     ``BlpImagePlugin.Format.JPEG`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED``           ``BlpImagePlugin.Encoding.UNCOMPRESSED`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_DXT``                    ``BlpImagePlugin.Encoding.DXT`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED_RAW_RGBA``  ``BlpImagePlugin.Encoding.UNCOMPRESSED_RAW_RGBA`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT1``             ``BlpImagePlugin.AlphaEncoding.DXT1`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT3``             ``BlpImagePlugin.AlphaEncoding.DXT3`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT5``             ``BlpImagePlugin.AlphaEncoding.DXT5`` | ||||
| ``FtexImagePlugin.FORMAT_DXT1``                        ``FtexImagePlugin.Format.DXT1`` | ||||
| ``FtexImagePlugin.FORMAT_UNCOMPRESSED``                ``FtexImagePlugin.Format.UNCOMPRESSED`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_NONE``                ``PngImagePlugin.Disposal.OP_NONE`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_BACKGROUND``          ``PngImagePlugin.Disposal.OP_BACKGROUND`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_PREVIOUS``            ``PngImagePlugin.Disposal.OP_PREVIOUS`` | ||||
| ``PngImagePlugin.APNG_BLEND_OP_SOURCE``                ``PngImagePlugin.Blend.OP_SOURCE`` | ||||
| ``PngImagePlugin.APNG_BLEND_OP_OVER``                  ``PngImagePlugin.Blend.OP_OVER`` | ||||
| =====================================================  ============================================================ | ||||
| 
 | ||||
| FitsStubImagePlugin | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.1.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| The stub image plugin ``FitsStubImagePlugin`` has been removed. | ||||
| FITS images can be read without a handler through :mod:`~PIL.FitsImagePlugin` instead. | ||||
| 
 | ||||
| FreeTypeFont.getmask2 fill parameter | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| The undocumented ``fill`` parameter of :py:meth:`.FreeTypeFont.getmask2` has been | ||||
| removed. | ||||
| 
 | ||||
| PhotoImage.paste box parameter | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| The ``box`` parameter was unused and has been removed. | ||||
| 
 | ||||
| PyQt5 and PySide2 | ||||
| ~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| `Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for | ||||
| open-source users (and will reach EOL on 2023-12-08 for commercial licence holders). | ||||
| 
 | ||||
| Support for PyQt5 and PySide2 has been removed from ``ImageQt``. Upgrade to | ||||
| `PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or | ||||
| `PySide6 <https://doc.qt.io/qtforpython/>`_ instead. | ||||
| 
 | ||||
| Image.coerce_e | ||||
| ~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| .. deprecated:: 9.2.0 | ||||
| .. versionremoved:: 10.0.0 | ||||
| 
 | ||||
| This undocumented method has been removed. | ||||
| 
 | ||||
| PILLOW_VERSION constant | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
|  |  | |||
|  | @ -412,18 +412,6 @@ See :ref:`concept-filters` for details. | |||
|     :undoc-members: | ||||
|     :noindex: | ||||
| 
 | ||||
| Some deprecated filters are also available under the following names: | ||||
| 
 | ||||
| .. data:: NONE | ||||
|     :noindex: | ||||
|     :value: Resampling.NEAREST | ||||
| .. data:: LINEAR | ||||
|     :value: Resampling.BILINEAR | ||||
| .. data:: CUBIC | ||||
|     :value: Resampling.BICUBIC | ||||
| .. data:: ANTIALIAS | ||||
|     :value: Resampling.LANCZOS | ||||
| 
 | ||||
| Dither modes | ||||
| ^^^^^^^^^^^^ | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,16 +4,8 @@ | |||
| :py:mod:`~PIL.ImageQt` Module | ||||
| ============================= | ||||
| 
 | ||||
| The :py:mod:`~PIL.ImageQt` module contains support for creating PyQt6, PySide6, PyQt5 | ||||
| or PySide2 QImage objects from PIL images. | ||||
| 
 | ||||
| `Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for | ||||
| open-source users (and will reach EOL on 2023-12-08 for commercial licence holders). | ||||
| 
 | ||||
| Support for PyQt5 and PySide2 has been deprecated from ``ImageQt`` and will be removed | ||||
| in Pillow 10 (2023-07-01). Upgrade to | ||||
| `PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or | ||||
| `PySide6 <https://doc.qt.io/qtforpython/>`_ instead. | ||||
| The :py:mod:`~PIL.ImageQt` module contains support for creating PyQt6 or PySide6 | ||||
| QImage objects from PIL images. | ||||
| 
 | ||||
| .. versionadded:: 1.1.6 | ||||
| 
 | ||||
|  | @ -22,7 +14,7 @@ in Pillow 10 (2023-07-01). Upgrade to | |||
|     Creates an :py:class:`~PIL.ImageQt.ImageQt` object from a PIL | ||||
|     :py:class:`~PIL.Image.Image` object. This class is a subclass of | ||||
|     QtGui.QImage, which means that you can pass the resulting objects directly | ||||
|     to PyQt6/PySide6/PyQt5/PySide2 API functions and methods. | ||||
|     to PyQt6/PySide6 API functions and methods. | ||||
| 
 | ||||
|     This operation is currently supported for mode 1, L, P, RGB, and RGBA | ||||
|     images. To handle other modes, you need to convert the image first. | ||||
|  |  | |||
							
								
								
									
										149
									
								
								docs/releasenotes/10.0.0.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								docs/releasenotes/10.0.0.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,149 @@ | |||
| 10.0.0 | ||||
| ------ | ||||
| 
 | ||||
| Backwards Incompatible Changes | ||||
| ============================== | ||||
| 
 | ||||
| Categories | ||||
| ^^^^^^^^^^ | ||||
| 
 | ||||
| ``im.category`` has been removed, along with the related ``Image.NORMAL``, | ||||
| ``Image.SEQUENCE`` and ``Image.CONTAINER`` attributes. | ||||
| 
 | ||||
| To determine if an image has multiple frames or not, | ||||
| ``getattr(im, "is_animated", False)`` can be used instead. | ||||
| 
 | ||||
| Tk/Tcl 8.4 | ||||
| ^^^^^^^^^^ | ||||
| 
 | ||||
| Support for Tk/Tcl 8.4 has been removed. | ||||
| 
 | ||||
| JpegImagePlugin.convert_dict_qtables | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| Since deprecation in Pillow 8.3.0, the ``convert_dict_qtables`` method no longer | ||||
| performed any operations on the data given to it, and has been removed. | ||||
| 
 | ||||
| ImagePalette size parameter | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| Before Pillow 8.3.0, ``ImagePalette`` required palette data of particular lengths by | ||||
| default, and the ``size`` parameter could be used to override that. Pillow 8.3.0 | ||||
| removed the default required length, also removing the need for the ``size`` parameter. | ||||
| 
 | ||||
| ImageShow.Viewer.show_file file argument | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| The ``file`` argument in :py:meth:`~PIL.ImageShow.Viewer.show_file()` has been | ||||
| removed and replaced by ``path``. | ||||
| 
 | ||||
| In effect, ``viewer.show_file("test.jpg")`` will continue to work unchanged. | ||||
| 
 | ||||
| Constants | ||||
| ^^^^^^^^^ | ||||
| 
 | ||||
| A number of constants have been removed. | ||||
| Instead, ``enum.IntEnum`` classes have been added. | ||||
| 
 | ||||
| =====================================================  ============================================================ | ||||
| Removed                                                Use instead | ||||
| =====================================================  ============================================================ | ||||
| ``Image.LINEAR``                                       ``Image.BILINEAR`` or ``Image.Resampling.BILINEAR`` | ||||
| ``Image.CUBIC``                                        ``Image.BICUBIC`` or ``Image.Resampling.BICUBIC`` | ||||
| ``Image.ANTIALIAS``                                    ``Image.LANCZOS`` or ``Image.Resampling.LANCZOS`` | ||||
| ``ImageCms.INTENT_PERCEPTUAL``                         ``ImageCms.Intent.PERCEPTUAL`` | ||||
| ``ImageCms.INTENT_RELATIVE_COLORMETRIC``               ``ImageCms.Intent.RELATIVE_COLORMETRIC`` | ||||
| ``ImageCms.INTENT_SATURATION``                         ``ImageCms.Intent.SATURATION`` | ||||
| ``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC``              ``ImageCms.Intent.ABSOLUTE_COLORIMETRIC`` | ||||
| ``ImageCms.DIRECTION_INPUT``                           ``ImageCms.Direction.INPUT`` | ||||
| ``ImageCms.DIRECTION_OUTPUT``                          ``ImageCms.Direction.OUTPUT`` | ||||
| ``ImageCms.DIRECTION_PROOF``                           ``ImageCms.Direction.PROOF`` | ||||
| ``ImageFont.LAYOUT_BASIC``                             ``ImageFont.Layout.BASIC`` | ||||
| ``ImageFont.LAYOUT_RAQM``                              ``ImageFont.Layout.RAQM`` | ||||
| ``BlpImagePlugin.BLP_FORMAT_JPEG``                     ``BlpImagePlugin.Format.JPEG`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED``           ``BlpImagePlugin.Encoding.UNCOMPRESSED`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_DXT``                    ``BlpImagePlugin.Encoding.DXT`` | ||||
| ``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED_RAW_RGBA``  ``BlpImagePlugin.Encoding.UNCOMPRESSED_RAW_RGBA`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT1``             ``BlpImagePlugin.AlphaEncoding.DXT1`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT3``             ``BlpImagePlugin.AlphaEncoding.DXT3`` | ||||
| ``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT5``             ``BlpImagePlugin.AlphaEncoding.DXT5`` | ||||
| ``FtexImagePlugin.FORMAT_DXT1``                        ``FtexImagePlugin.Format.DXT1`` | ||||
| ``FtexImagePlugin.FORMAT_UNCOMPRESSED``                ``FtexImagePlugin.Format.UNCOMPRESSED`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_NONE``                ``PngImagePlugin.Disposal.OP_NONE`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_BACKGROUND``          ``PngImagePlugin.Disposal.OP_BACKGROUND`` | ||||
| ``PngImagePlugin.APNG_DISPOSE_OP_PREVIOUS``            ``PngImagePlugin.Disposal.OP_PREVIOUS`` | ||||
| ``PngImagePlugin.APNG_BLEND_OP_SOURCE``                ``PngImagePlugin.Blend.OP_SOURCE`` | ||||
| ``PngImagePlugin.APNG_BLEND_OP_OVER``                  ``PngImagePlugin.Blend.OP_OVER`` | ||||
| =====================================================  ============================================================ | ||||
| 
 | ||||
| FitsStubImagePlugin | ||||
| ^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| The stub image plugin ``FitsStubImagePlugin`` has been removed. | ||||
| FITS images can be read without a handler through :mod:`~PIL.FitsImagePlugin` instead. | ||||
| 
 | ||||
| FreeTypeFont.getmask2 fill parameter | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| The undocumented ``fill`` parameter of :py:meth:`.FreeTypeFont.getmask2` has been | ||||
| removed. | ||||
| 
 | ||||
| PhotoImage.paste box parameter | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| The ``box`` parameter was unused and has been removed. | ||||
| 
 | ||||
| PyQt5 and PySide2 | ||||
| ^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| `Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for | ||||
| open-source users (and will reach EOL on 2023-12-08 for commercial licence holders). | ||||
| 
 | ||||
| Support for PyQt5 and PySide2 has been removed from ``ImageQt``. Upgrade to | ||||
| `PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or | ||||
| `PySide6 <https://doc.qt.io/qtforpython/>`_ instead. | ||||
| 
 | ||||
| Image.coerce_e | ||||
| ^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| This undocumented method has been removed. | ||||
| 
 | ||||
| Deprecations | ||||
| ============ | ||||
| 
 | ||||
| TODO | ||||
| ^^^^ | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| API Changes | ||||
| =========== | ||||
| 
 | ||||
| TODO | ||||
| ^^^^ | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| API Additions | ||||
| ============= | ||||
| 
 | ||||
| TODO | ||||
| ^^^^ | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| Security | ||||
| ======== | ||||
| 
 | ||||
| TODO | ||||
| ^^^^ | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| Other Changes | ||||
| ============= | ||||
| 
 | ||||
| TODO | ||||
| ^^^^ | ||||
| 
 | ||||
| TODO | ||||
|  | @ -8,7 +8,7 @@ JpegImagePlugin.convert_dict_qtables | |||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| JPEG ``quantization`` is now automatically converted, but still returned as a | ||||
| dictionary. The :py:attr:`~PIL.JpegImagePlugin.convert_dict_qtables` method no longer | ||||
| dictionary. The ``convert_dict_qtables`` method no longer | ||||
| performs any operations on the data given to it, has been deprecated and will be | ||||
| removed in Pillow 10.0.0 (2023-07-01). | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ expected to be backported to earlier versions. | |||
| .. toctree:: | ||||
|   :maxdepth: 2 | ||||
| 
 | ||||
|   10.0.0 | ||||
|   9.5.0 | ||||
|   9.4.0 | ||||
|   9.3.0 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| x.y.z | ||||
| ----- | ||||
| xx.y.z | ||||
| ------ | ||||
| 
 | ||||
| Backwards Incompatible Changes | ||||
| ============================== | ||||
|  |  | |||
							
								
								
									
										4
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -685,10 +685,6 @@ class pil_build_ext(build_ext): | |||
|                 # Add the directory to the include path so we can include | ||||
|                 # <openjpeg.h> rather than having to cope with the versioned | ||||
|                 # include path | ||||
|                 # FIXME (melvyn-sopacua): | ||||
|                 # At this point it's possible that best_path is already in | ||||
|                 # self.compiler.include_dirs. Should investigate how that is | ||||
|                 # possible. | ||||
|                 _add_directory(self.compiler.include_dirs, best_path, 0) | ||||
|                 feature.jpeg2000 = "openjp2" | ||||
|                 feature.openjpeg_version = ".".join(str(x) for x in best_version) | ||||
|  |  | |||
|  | @ -35,7 +35,6 @@ from enum import IntEnum | |||
| from io import BytesIO | ||||
| 
 | ||||
| from . import Image, ImageFile | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| 
 | ||||
| class Format(IntEnum): | ||||
|  | @ -54,21 +53,6 @@ class AlphaEncoding(IntEnum): | |||
|     DXT5 = 7 | ||||
| 
 | ||||
| 
 | ||||
| def __getattr__(name): | ||||
|     for enum, prefix in { | ||||
|         Format: "BLP_FORMAT_", | ||||
|         Encoding: "BLP_ENCODING_", | ||||
|         AlphaEncoding: "BLP_ALPHA_ENCODING_", | ||||
|     }.items(): | ||||
|         if name.startswith(prefix): | ||||
|             name = name[len(prefix) :] | ||||
|             if name in enum.__members__: | ||||
|                 deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") | ||||
|                 return enum[name] | ||||
|     msg = f"module '{__name__}' has no attribute '{name}'" | ||||
|     raise AttributeError(msg) | ||||
| 
 | ||||
| 
 | ||||
| def unpack_565(i): | ||||
|     return ((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,76 +0,0 @@ | |||
| # | ||||
| # The Python Imaging Library | ||||
| # $Id$ | ||||
| # | ||||
| # FITS stub adapter | ||||
| # | ||||
| # Copyright (c) 1998-2003 by Fredrik Lundh | ||||
| # | ||||
| # See the README file for information on usage and redistribution. | ||||
| # | ||||
| 
 | ||||
| from . import FitsImagePlugin, Image, ImageFile | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| _handler = None | ||||
| 
 | ||||
| 
 | ||||
| def register_handler(handler): | ||||
|     """ | ||||
|     Install application-specific FITS image handler. | ||||
| 
 | ||||
|     :param handler: Handler object. | ||||
|     """ | ||||
|     global _handler | ||||
|     _handler = handler | ||||
| 
 | ||||
|     deprecate( | ||||
|         "FitsStubImagePlugin", | ||||
|         10, | ||||
|         action="FITS images can now be read without " | ||||
|         "a handler through FitsImagePlugin instead", | ||||
|     ) | ||||
| 
 | ||||
|     # Override FitsImagePlugin with this handler | ||||
|     # for backwards compatibility | ||||
|     try: | ||||
|         Image.ID.remove(FITSStubImageFile.format) | ||||
|     except ValueError: | ||||
|         pass | ||||
| 
 | ||||
|     Image.register_open( | ||||
|         FITSStubImageFile.format, FITSStubImageFile, FitsImagePlugin._accept | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| class FITSStubImageFile(ImageFile.StubImageFile): | ||||
|     format = FitsImagePlugin.FitsImageFile.format | ||||
|     format_description = FitsImagePlugin.FitsImageFile.format_description | ||||
| 
 | ||||
|     def _open(self): | ||||
|         offset = self.fp.tell() | ||||
| 
 | ||||
|         im = FitsImagePlugin.FitsImageFile(self.fp) | ||||
|         self._size = im.size | ||||
|         self.mode = im.mode | ||||
|         self.tile = [] | ||||
| 
 | ||||
|         self.fp.seek(offset) | ||||
| 
 | ||||
|         loader = self._load() | ||||
|         if loader: | ||||
|             loader.open(self) | ||||
| 
 | ||||
|     def _load(self): | ||||
|         return _handler | ||||
| 
 | ||||
| 
 | ||||
| def _save(im, fp, filename): | ||||
|     msg = "FITS save handler not installed" | ||||
|     raise OSError(msg) | ||||
| 
 | ||||
| 
 | ||||
| # -------------------------------------------------------------------- | ||||
| # Registry | ||||
| 
 | ||||
| Image.register_save(FITSStubImageFile.format, _save) | ||||
|  | @ -56,7 +56,6 @@ from enum import IntEnum | |||
| from io import BytesIO | ||||
| 
 | ||||
| from . import Image, ImageFile | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| MAGIC = b"FTEX" | ||||
| 
 | ||||
|  | @ -66,17 +65,6 @@ class Format(IntEnum): | |||
|     UNCOMPRESSED = 1 | ||||
| 
 | ||||
| 
 | ||||
| def __getattr__(name): | ||||
|     for enum, prefix in {Format: "FORMAT_"}.items(): | ||||
|         if name.startswith(prefix): | ||||
|             name = name[len(prefix) :] | ||||
|             if name in enum.__members__: | ||||
|                 deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") | ||||
|                 return enum[name] | ||||
|     msg = f"module '{__name__}' has no attribute '{name}'" | ||||
|     raise AttributeError(msg) | ||||
| 
 | ||||
| 
 | ||||
| class FtexImageFile(ImageFile.ImageFile): | ||||
|     format = "FTEX" | ||||
|     format_description = "Texture File Format (IW2:EOC)" | ||||
|  |  | |||
|  | @ -56,29 +56,8 @@ from . import ( | |||
|     _plugins, | ||||
| ) | ||||
| from ._binary import i32le, o32be, o32le | ||||
| from ._deprecate import deprecate | ||||
| from ._util import DeferredError, is_path | ||||
| 
 | ||||
| 
 | ||||
| def __getattr__(name): | ||||
|     categories = {"NORMAL": 0, "SEQUENCE": 1, "CONTAINER": 2} | ||||
|     if name in categories: | ||||
|         deprecate("Image categories", 10, "is_animated", plural=True) | ||||
|         return categories[name] | ||||
|     old_resampling = { | ||||
|         "LINEAR": "BILINEAR", | ||||
|         "CUBIC": "BICUBIC", | ||||
|         "ANTIALIAS": "LANCZOS", | ||||
|     } | ||||
|     if name in old_resampling: | ||||
|         deprecate( | ||||
|             name, 10, f"{old_resampling[name]} or Resampling.{old_resampling[name]}" | ||||
|         ) | ||||
|         return Resampling[old_resampling[name]] | ||||
|     msg = f"module '{__name__}' has no attribute '{name}'" | ||||
|     raise AttributeError(msg) | ||||
| 
 | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -441,26 +420,18 @@ def _getencoder(mode, encoder_name, args, extra=()): | |||
| # Simple expression analyzer | ||||
| 
 | ||||
| 
 | ||||
| def coerce_e(value): | ||||
|     deprecate("coerce_e", 10) | ||||
|     return value if isinstance(value, _E) else _E(1, value) | ||||
| 
 | ||||
| 
 | ||||
| # _E(scale, offset) represents the affine transformation scale * x + offset. | ||||
| # The "data" field is named for compatibility with the old implementation, | ||||
| # and should be renamed once coerce_e is removed. | ||||
| class _E: | ||||
|     def __init__(self, scale, data): | ||||
|     def __init__(self, scale, offset): | ||||
|         self.scale = scale | ||||
|         self.data = data | ||||
|         self.offset = offset | ||||
| 
 | ||||
|     def __neg__(self): | ||||
|         return _E(-self.scale, -self.data) | ||||
|         return _E(-self.scale, -self.offset) | ||||
| 
 | ||||
|     def __add__(self, other): | ||||
|         if isinstance(other, _E): | ||||
|             return _E(self.scale + other.scale, self.data + other.data) | ||||
|         return _E(self.scale, self.data + other) | ||||
|             return _E(self.scale + other.scale, self.offset + other.offset) | ||||
|         return _E(self.scale, self.offset + other) | ||||
| 
 | ||||
|     __radd__ = __add__ | ||||
| 
 | ||||
|  | @ -473,19 +444,19 @@ class _E: | |||
|     def __mul__(self, other): | ||||
|         if isinstance(other, _E): | ||||
|             return NotImplemented | ||||
|         return _E(self.scale * other, self.data * other) | ||||
|         return _E(self.scale * other, self.offset * other) | ||||
| 
 | ||||
|     __rmul__ = __mul__ | ||||
| 
 | ||||
|     def __truediv__(self, other): | ||||
|         if isinstance(other, _E): | ||||
|             return NotImplemented | ||||
|         return _E(self.scale / other, self.data / other) | ||||
|         return _E(self.scale / other, self.offset / other) | ||||
| 
 | ||||
| 
 | ||||
| def _getscaleoffset(expr): | ||||
|     a = expr(_E(1, 0)) | ||||
|     return (a.scale, a.data) if isinstance(a, _E) else (0, a) | ||||
|     return (a.scale, a.offset) if isinstance(a, _E) else (0, a) | ||||
| 
 | ||||
| 
 | ||||
| # -------------------------------------------------------------------- | ||||
|  | @ -516,17 +487,10 @@ class Image: | |||
|         self._size = (0, 0) | ||||
|         self.palette = None | ||||
|         self.info = {} | ||||
|         self._category = 0 | ||||
|         self.readonly = 0 | ||||
|         self.pyaccess = None | ||||
|         self._exif = None | ||||
| 
 | ||||
|     def __getattr__(self, name): | ||||
|         if name == "category": | ||||
|             deprecate("Image categories", 10, "is_animated", plural=True) | ||||
|             return self._category | ||||
|         raise AttributeError(name) | ||||
| 
 | ||||
|     @property | ||||
|     def width(self): | ||||
|         return self.size[0] | ||||
|  | @ -639,7 +603,6 @@ class Image: | |||
|             and self.mode == other.mode | ||||
|             and self.size == other.size | ||||
|             and self.info == other.info | ||||
|             and self._category == other._category | ||||
|             and self.getpalette() == other.getpalette() | ||||
|             and self.tobytes() == other.tobytes() | ||||
|         ) | ||||
|  |  | |||
|  | @ -20,8 +20,6 @@ from enum import IntEnum | |||
| 
 | ||||
| from PIL import Image | ||||
| 
 | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| try: | ||||
|     from PIL import _imagingcms | ||||
| except ImportError as ex: | ||||
|  | @ -117,17 +115,6 @@ class Direction(IntEnum): | |||
|     PROOF = 2 | ||||
| 
 | ||||
| 
 | ||||
| def __getattr__(name): | ||||
|     for enum, prefix in {Intent: "INTENT_", Direction: "DIRECTION_"}.items(): | ||||
|         if name.startswith(prefix): | ||||
|             name = name[len(prefix) :] | ||||
|             if name in enum.__members__: | ||||
|                 deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") | ||||
|                 return enum[name] | ||||
|     msg = f"module '{__name__}' has no attribute '{name}'" | ||||
|     raise AttributeError(msg) | ||||
| 
 | ||||
| 
 | ||||
| # | ||||
| # flags | ||||
| 
 | ||||
|  |  | |||
|  | @ -43,17 +43,6 @@ class Layout(IntEnum): | |||
|     RAQM = 1 | ||||
| 
 | ||||
| 
 | ||||
| def __getattr__(name): | ||||
|     for enum, prefix in {Layout: "LAYOUT_"}.items(): | ||||
|         if name.startswith(prefix): | ||||
|             name = name[len(prefix) :] | ||||
|             if name in enum.__members__: | ||||
|                 deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") | ||||
|                 return enum[name] | ||||
|     msg = f"module '{__name__}' has no attribute '{name}'" | ||||
|     raise AttributeError(msg) | ||||
| 
 | ||||
| 
 | ||||
| try: | ||||
|     from . import _imagingft as core | ||||
| except ImportError as ex: | ||||
|  | @ -62,9 +51,6 @@ except ImportError as ex: | |||
|     core = DeferredError(ex) | ||||
| 
 | ||||
| 
 | ||||
| _UNSPECIFIED = object() | ||||
| 
 | ||||
| 
 | ||||
| # FIXME: add support for pilfont2 format (see FontFile.py) | ||||
| 
 | ||||
| # -------------------------------------------------------------------- | ||||
|  | @ -665,7 +651,6 @@ class FreeTypeFont: | |||
|         self, | ||||
|         text, | ||||
|         mode="", | ||||
|         fill=_UNSPECIFIED, | ||||
|         direction=None, | ||||
|         features=None, | ||||
|         language=None, | ||||
|  | @ -691,12 +676,6 @@ class FreeTypeFont: | |||
| 
 | ||||
|                      .. versionadded:: 1.1.5 | ||||
| 
 | ||||
|         :param fill: Optional fill function. By default, an internal Pillow function | ||||
|                      will be used. | ||||
| 
 | ||||
|                      Deprecated. This parameter will be removed in Pillow 10 | ||||
|                      (2023-07-01). | ||||
| 
 | ||||
|         :param direction: Direction of the text. It can be 'rtl' (right to | ||||
|                           left), 'ltr' (left to right) or 'ttb' (top to bottom). | ||||
|                           Requires libraqm. | ||||
|  | @ -749,10 +728,6 @@ class FreeTypeFont: | |||
|                  :py:mod:`PIL.Image.core` interface module, and the text offset, the | ||||
|                  gap between the starting coordinate and the first marking | ||||
|         """ | ||||
|         if fill is _UNSPECIFIED: | ||||
|             fill = Image.core.fill | ||||
|         else: | ||||
|             deprecate("fill", 10) | ||||
|         size, offset = self.font.getsize( | ||||
|             text, mode, direction, features, language, anchor | ||||
|         ) | ||||
|  | @ -761,7 +736,7 @@ class FreeTypeFont: | |||
|         size = tuple(math.ceil(size[i] + stroke_width * 2 + start[i]) for i in range(2)) | ||||
|         offset = offset[0] - stroke_width, offset[1] - stroke_width | ||||
|         Image._decompression_bomb_check(size) | ||||
|         im = fill("RGBA" if mode == "RGBA" else "L", size, 0) | ||||
|         im = Image.core.fill("RGBA" if mode == "RGBA" else "L", size, 0) | ||||
|         if min(size): | ||||
|             self.font.render( | ||||
|                 text, | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ | |||
| import array | ||||
| 
 | ||||
| from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| 
 | ||||
| class ImagePalette: | ||||
|  | @ -34,16 +33,11 @@ class ImagePalette: | |||
|         Defaults to an empty palette. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, mode="RGB", palette=None, size=0): | ||||
|     def __init__(self, mode="RGB", palette=None): | ||||
|         self.mode = mode | ||||
|         self.rawmode = None  # if set, palette contains raw data | ||||
|         self.palette = palette or bytearray() | ||||
|         self.dirty = None | ||||
|         if size != 0: | ||||
|             deprecate("The size parameter", 10, None) | ||||
|             if size != len(self.palette): | ||||
|                 msg = "wrong palette size" | ||||
|                 raise ValueError(msg) | ||||
| 
 | ||||
|     @property | ||||
|     def palette(self): | ||||
|  |  | |||
|  | @ -20,14 +20,11 @@ import sys | |||
| from io import BytesIO | ||||
| 
 | ||||
| from . import Image | ||||
| from ._deprecate import deprecate | ||||
| from ._util import is_path | ||||
| 
 | ||||
| qt_versions = [ | ||||
|     ["6", "PyQt6"], | ||||
|     ["side6", "PySide6"], | ||||
|     ["5", "PyQt5"], | ||||
|     ["side2", "PySide2"], | ||||
| ] | ||||
| 
 | ||||
| # If a version has already been imported, attempt it first | ||||
|  | @ -40,16 +37,6 @@ for qt_version, qt_module in qt_versions: | |||
|         elif qt_module == "PySide6": | ||||
|             from PySide6.QtCore import QBuffer, QIODevice | ||||
|             from PySide6.QtGui import QImage, QPixmap, qRgba | ||||
|         elif qt_module == "PyQt5": | ||||
|             from PyQt5.QtCore import QBuffer, QIODevice | ||||
|             from PyQt5.QtGui import QImage, QPixmap, qRgba | ||||
| 
 | ||||
|             deprecate("Support for PyQt5", 10, "PyQt6 or PySide6") | ||||
|         elif qt_module == "PySide2": | ||||
|             from PySide2.QtCore import QBuffer, QIODevice | ||||
|             from PySide2.QtGui import QImage, QPixmap, qRgba | ||||
| 
 | ||||
|             deprecate("Support for PySide2", 10, "PyQt6 or PySide6") | ||||
|     except (ImportError, RuntimeError): | ||||
|         continue | ||||
|     qt_is_installed = True | ||||
|  |  | |||
|  | @ -19,8 +19,6 @@ from shlex import quote | |||
| 
 | ||||
| from PIL import Image | ||||
| 
 | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| _viewers = [] | ||||
| 
 | ||||
| 
 | ||||
|  | @ -111,21 +109,10 @@ class Viewer: | |||
|         """Display the given image.""" | ||||
|         return self.show_file(self.save_image(image), **options) | ||||
| 
 | ||||
|     def show_file(self, path=None, **options): | ||||
|     def show_file(self, path, **options): | ||||
|         """ | ||||
|         Display given file. | ||||
| 
 | ||||
|         Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated, | ||||
|         and will be removed in Pillow 10.0.0 (2023-07-01). ``path`` should be used | ||||
|         instead. | ||||
|         """ | ||||
|         if path is None: | ||||
|             if "file" in options: | ||||
|                 deprecate("The 'file' argument", 10, "'path'") | ||||
|                 path = options.pop("file") | ||||
|             else: | ||||
|                 msg = "Missing required argument: 'path'" | ||||
|                 raise TypeError(msg) | ||||
|         os.system(self.get_command(path, **options))  # nosec | ||||
|         return 1 | ||||
| 
 | ||||
|  | @ -164,21 +151,10 @@ class MacViewer(Viewer): | |||
|         command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&" | ||||
|         return command | ||||
| 
 | ||||
|     def show_file(self, path=None, **options): | ||||
|     def show_file(self, path, **options): | ||||
|         """ | ||||
|         Display given file. | ||||
| 
 | ||||
|         Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated, | ||||
|         and will be removed in Pillow 10.0.0 (2023-07-01). ``path`` should be used | ||||
|         instead. | ||||
|         """ | ||||
|         if path is None: | ||||
|             if "file" in options: | ||||
|                 deprecate("The 'file' argument", 10, "'path'") | ||||
|                 path = options.pop("file") | ||||
|             else: | ||||
|                 msg = "Missing required argument: 'path'" | ||||
|                 raise TypeError(msg) | ||||
|         subprocess.call(["open", "-a", "Preview.app", path]) | ||||
|         executable = sys.executable or shutil.which("python3") | ||||
|         if executable: | ||||
|  | @ -215,21 +191,10 @@ class XDGViewer(UnixViewer): | |||
|         command = executable = "xdg-open" | ||||
|         return command, executable | ||||
| 
 | ||||
|     def show_file(self, path=None, **options): | ||||
|     def show_file(self, path, **options): | ||||
|         """ | ||||
|         Display given file. | ||||
| 
 | ||||
|         Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated, | ||||
|         and will be removed in Pillow 10.0.0 (2023-07-01). ``path`` should be used | ||||
|         instead. | ||||
|         """ | ||||
|         if path is None: | ||||
|             if "file" in options: | ||||
|                 deprecate("The 'file' argument", 10, "'path'") | ||||
|                 path = options.pop("file") | ||||
|             else: | ||||
|                 msg = "Missing required argument: 'path'" | ||||
|                 raise TypeError(msg) | ||||
|         subprocess.Popen(["xdg-open", path]) | ||||
|         return 1 | ||||
| 
 | ||||
|  | @ -246,20 +211,10 @@ class DisplayViewer(UnixViewer): | |||
|             command += f" -title {quote(title)}" | ||||
|         return command, executable | ||||
| 
 | ||||
|     def show_file(self, path=None, **options): | ||||
|     def show_file(self, path, **options): | ||||
|         """ | ||||
|         Display given file. | ||||
| 
 | ||||
|         Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated, | ||||
|         and ``path`` should be used instead. | ||||
|         """ | ||||
|         if path is None: | ||||
|             if "file" in options: | ||||
|                 deprecate("The 'file' argument", 10, "'path'") | ||||
|                 path = options.pop("file") | ||||
|             else: | ||||
|                 msg = "Missing required argument: 'path'" | ||||
|                 raise TypeError(msg) | ||||
|         args = ["display"] | ||||
|         title = options.get("title") | ||||
|         if title: | ||||
|  | @ -278,20 +233,10 @@ class GmDisplayViewer(UnixViewer): | |||
|         command = "gm display" | ||||
|         return command, executable | ||||
| 
 | ||||
|     def show_file(self, path=None, **options): | ||||
|     def show_file(self, path, **options): | ||||
|         """ | ||||
|         Display given file. | ||||
| 
 | ||||
|         Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated, | ||||
|         and ``path`` should be used instead. | ||||
|         """ | ||||
|         if path is None: | ||||
|             if "file" in options: | ||||
|                 deprecate("The 'file' argument", 10, "'path'") | ||||
|                 path = options.pop("file") | ||||
|             else: | ||||
|                 msg = "Missing required argument: 'path'" | ||||
|                 raise TypeError(msg) | ||||
|         subprocess.Popen(["gm", "display", path]) | ||||
|         return 1 | ||||
| 
 | ||||
|  | @ -304,20 +249,10 @@ class EogViewer(UnixViewer): | |||
|         command = "eog -n" | ||||
|         return command, executable | ||||
| 
 | ||||
|     def show_file(self, path=None, **options): | ||||
|     def show_file(self, path, **options): | ||||
|         """ | ||||
|         Display given file. | ||||
| 
 | ||||
|         Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated, | ||||
|         and ``path`` should be used instead. | ||||
|         """ | ||||
|         if path is None: | ||||
|             if "file" in options: | ||||
|                 deprecate("The 'file' argument", 10, "'path'") | ||||
|                 path = options.pop("file") | ||||
|             else: | ||||
|                 msg = "Missing required argument: 'path'" | ||||
|                 raise TypeError(msg) | ||||
|         subprocess.Popen(["eog", "-n", path]) | ||||
|         return 1 | ||||
| 
 | ||||
|  | @ -336,20 +271,10 @@ class XVViewer(UnixViewer): | |||
|             command += f" -name {quote(title)}" | ||||
|         return command, executable | ||||
| 
 | ||||
|     def show_file(self, path=None, **options): | ||||
|     def show_file(self, path, **options): | ||||
|         """ | ||||
|         Display given file. | ||||
| 
 | ||||
|         Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated, | ||||
|         and ``path`` should be used instead. | ||||
|         """ | ||||
|         if path is None: | ||||
|             if "file" in options: | ||||
|                 deprecate("The 'file' argument", 10, "'path'") | ||||
|                 path = options.pop("file") | ||||
|             else: | ||||
|                 msg = "Missing required argument: 'path'" | ||||
|                 raise TypeError(msg) | ||||
|         args = ["xv"] | ||||
|         title = options.get("title") | ||||
|         if title: | ||||
|  |  | |||
|  | @ -29,7 +29,6 @@ import tkinter | |||
| from io import BytesIO | ||||
| 
 | ||||
| from . import Image | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| # -------------------------------------------------------------------- | ||||
| # Check for Tkinter interface hooks | ||||
|  | @ -162,7 +161,7 @@ class PhotoImage: | |||
|         """ | ||||
|         return self.__size[1] | ||||
| 
 | ||||
|     def paste(self, im, box=None): | ||||
|     def paste(self, im): | ||||
|         """ | ||||
|         Paste a PIL image into the photo image.  Note that this can | ||||
|         be very slow if the photo image is displayed. | ||||
|  | @ -170,13 +169,7 @@ class PhotoImage: | |||
|         :param im: A PIL image. The size must match the target region.  If the | ||||
|                    mode does not match, the image is converted to the mode of | ||||
|                    the bitmap image. | ||||
|         :param box: Deprecated. This parameter will be removed in Pillow 10 | ||||
|                     (2023-07-01). | ||||
|         """ | ||||
| 
 | ||||
|         if box is not None: | ||||
|             deprecate("The box parameter", 10, None) | ||||
| 
 | ||||
|         # convert to blittable | ||||
|         im.load() | ||||
|         image = im.im | ||||
|  |  | |||
|  | @ -46,7 +46,6 @@ from ._binary import i16be as i16 | |||
| from ._binary import i32be as i32 | ||||
| from ._binary import o8 | ||||
| from ._binary import o16be as o16 | ||||
| from ._deprecate import deprecate | ||||
| from .JpegPresets import presets | ||||
| 
 | ||||
| # | ||||
|  | @ -612,11 +611,6 @@ samplings = { | |||
| # fmt: on | ||||
| 
 | ||||
| 
 | ||||
| def convert_dict_qtables(qtables): | ||||
|     deprecate("convert_dict_qtables", 10, action="Conversion is no longer needed") | ||||
|     return qtables | ||||
| 
 | ||||
| 
 | ||||
| def get_sampling(im): | ||||
|     # There's no subsampling when images have only 1 layer | ||||
|     # (grayscale images) or when they are CMYK (4 layers), | ||||
|  |  | |||
|  | @ -66,9 +66,6 @@ class MicImageFile(TiffImagePlugin.TiffImageFile): | |||
|         self._n_frames = len(self.images) | ||||
|         self.is_animated = self._n_frames > 1 | ||||
| 
 | ||||
|         if len(self.images) > 1: | ||||
|             self._category = Image.CONTAINER | ||||
| 
 | ||||
|         self.seek(0) | ||||
| 
 | ||||
|     def seek(self, frame): | ||||
|  |  | |||
|  | @ -45,7 +45,6 @@ from ._binary import i32be as i32 | |||
| from ._binary import o8 | ||||
| from ._binary import o16be as o16 | ||||
| from ._binary import o32be as o32 | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
|  | @ -131,17 +130,6 @@ class Blend(IntEnum): | |||
|     """ | ||||
| 
 | ||||
| 
 | ||||
| def __getattr__(name): | ||||
|     for enum, prefix in {Disposal: "APNG_DISPOSE_", Blend: "APNG_BLEND_"}.items(): | ||||
|         if name.startswith(prefix): | ||||
|             name = name[len(prefix) :] | ||||
|             if name in enum.__members__: | ||||
|                 deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}") | ||||
|                 return enum[name] | ||||
|     msg = f"module '{__name__}' has no attribute '{name}'" | ||||
|     raise AttributeError(msg) | ||||
| 
 | ||||
| 
 | ||||
| def _safe_zlib_decompress(s): | ||||
|     dobj = zlib.decompressobj() | ||||
|     plaintext = dobj.decompress(s, MAX_TEXT_CHUNK) | ||||
|  |  | |||
|  | @ -31,7 +31,6 @@ _plugins = [ | |||
|     "DdsImagePlugin", | ||||
|     "EpsImagePlugin", | ||||
|     "FitsImagePlugin", | ||||
|     "FitsStubImagePlugin", | ||||
|     "FliImagePlugin", | ||||
|     "FpxImagePlugin", | ||||
|     "FtexImagePlugin", | ||||
|  |  | |||
|  | @ -4,8 +4,6 @@ import sys | |||
| import tkinter | ||||
| from tkinter import _tkinter as tk | ||||
| 
 | ||||
| from ._deprecate import deprecate | ||||
| 
 | ||||
| try: | ||||
|     if hasattr(sys, "pypy_find_executable"): | ||||
|         TKINTER_LIB = tk.tklib_cffi.__file__ | ||||
|  | @ -17,7 +15,3 @@ except AttributeError: | |||
|     TKINTER_LIB = None | ||||
| 
 | ||||
| tk_version = str(tkinter.TkVersion) | ||||
| if tk_version == "8.4": | ||||
|     deprecate( | ||||
|         "Support for Tk/Tcl 8.4", 10, action="Please upgrade to Tk/Tcl 8.5 or newer" | ||||
|     ) | ||||
|  |  | |||
|  | @ -119,17 +119,7 @@ typedef struct Tk_PhotoImageBlock { | |||
| } Tk_PhotoImageBlock; | ||||
| 
 | ||||
| /* Typedefs derived from function signatures in Tk header */ | ||||
| /* Tk_PhotoPutBlock for Tk <= 8.4 */ | ||||
| typedef void (*Tk_PhotoPutBlock_84_t)( | ||||
|     Tk_PhotoHandle handle, | ||||
|     Tk_PhotoImageBlock *blockPtr, | ||||
|     int x, | ||||
|     int y, | ||||
|     int width, | ||||
|     int height, | ||||
|     int compRule); | ||||
| /* Tk_PhotoPutBlock for Tk >= 8.5 */ | ||||
| typedef int (*Tk_PhotoPutBlock_85_t)( | ||||
| typedef int (*Tk_PhotoPutBlock_t)( | ||||
|     Tcl_Interp *interp, | ||||
|     Tk_PhotoHandle handle, | ||||
|     Tk_PhotoImageBlock *blockPtr, | ||||
|  | @ -138,8 +128,6 @@ typedef int (*Tk_PhotoPutBlock_85_t)( | |||
|     int width, | ||||
|     int height, | ||||
|     int compRule); | ||||
| /* Tk_PhotoSetSize for Tk <= 8.4 */ | ||||
| typedef void (*Tk_PhotoSetSize_84_t)(Tk_PhotoHandle handle, int width, int height); | ||||
| /* Tk_FindPhoto */ | ||||
| typedef Tk_PhotoHandle (*Tk_FindPhoto_t)(Tcl_Interp *interp, const char *imageName); | ||||
| /* Tk_PhotoGetImage */ | ||||
|  |  | |||
|  | @ -48,14 +48,11 @@ | |||
|  * Global vars for Tcl / Tk functions.  We load these symbols from the tkinter | ||||
|  * extension module or loaded Tcl / Tk libraries at run-time. | ||||
|  */ | ||||
| static int TK_LT_85 = 0; | ||||
| static Tcl_CreateCommand_t TCL_CREATE_COMMAND; | ||||
| static Tcl_AppendResult_t TCL_APPEND_RESULT; | ||||
| static Tk_FindPhoto_t TK_FIND_PHOTO; | ||||
| static Tk_PhotoGetImage_t TK_PHOTO_GET_IMAGE; | ||||
| static Tk_PhotoPutBlock_84_t TK_PHOTO_PUT_BLOCK_84; | ||||
| static Tk_PhotoSetSize_84_t TK_PHOTO_SET_SIZE_84; | ||||
| static Tk_PhotoPutBlock_85_t TK_PHOTO_PUT_BLOCK_85; | ||||
| static Tk_PhotoPutBlock_t TK_PHOTO_PUT_BLOCK; | ||||
| 
 | ||||
| static Imaging | ||||
| ImagingFind(const char *name) { | ||||
|  | @ -130,26 +127,15 @@ PyImagingPhotoPut( | |||
|     block.pitch = im->linesize; | ||||
|     block.pixelPtr = (unsigned char *)im->block; | ||||
| 
 | ||||
|     if (TK_LT_85) { /* Tk 8.4 */ | ||||
|         TK_PHOTO_PUT_BLOCK_84( | ||||
|             photo, &block, 0, 0, block.width, block.height, TK_PHOTO_COMPOSITE_SET); | ||||
|         if (strcmp(im->mode, "RGBA") == 0) { | ||||
|             /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */ | ||||
|             /* (fixed in Tk 8.5a3) */ | ||||
|             TK_PHOTO_SET_SIZE_84(photo, block.width, block.height); | ||||
|         } | ||||
|     } else { | ||||
|         /* Tk >=8.5 */ | ||||
|         TK_PHOTO_PUT_BLOCK_85( | ||||
|             interp, | ||||
|             photo, | ||||
|             &block, | ||||
|             0, | ||||
|             0, | ||||
|             block.width, | ||||
|             block.height, | ||||
|             TK_PHOTO_COMPOSITE_SET); | ||||
|     } | ||||
|     TK_PHOTO_PUT_BLOCK( | ||||
|         interp, | ||||
|         photo, | ||||
|         &block, | ||||
|         0, | ||||
|         0, | ||||
|         block.width, | ||||
|         block.height, | ||||
|         TK_PHOTO_COMPOSITE_SET); | ||||
| 
 | ||||
|     return TCL_OK; | ||||
| } | ||||
|  | @ -290,16 +276,7 @@ get_tk(HMODULE hMod) { | |||
|     if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(hMod, "Tk_FindPhoto")) == NULL) { | ||||
|         return -1; | ||||
|     }; | ||||
|     TK_LT_85 = GetProcAddress(hMod, "Tk_PhotoPutBlock_Panic") == NULL; | ||||
|     /* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */ | ||||
|     if (TK_LT_85) { | ||||
|         TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t)func; | ||||
|         return ((TK_PHOTO_SET_SIZE_84 = | ||||
|                      (Tk_PhotoSetSize_84_t)_dfunc(hMod, "Tk_PhotoSetSize")) == NULL) | ||||
|                    ? -1 | ||||
|                    : 1; | ||||
|     } | ||||
|     TK_PHOTO_PUT_BLOCK_85 = (Tk_PhotoPutBlock_85_t)func; | ||||
|     TK_PHOTO_PUT_BLOCK = (Tk_PhotoPutBlock_t)func; | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
|  | @ -422,18 +399,9 @@ _func_loader(void *lib) { | |||
|     if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(lib, "Tk_FindPhoto")) == NULL) { | ||||
|         return 1; | ||||
|     } | ||||
|     /* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */ | ||||
|     TK_LT_85 = (dlsym(lib, "Tk_PhotoPutBlock_Panic") == NULL); | ||||
|     if (TK_LT_85) { | ||||
|         return ( | ||||
|             ((TK_PHOTO_PUT_BLOCK_84 = | ||||
|                   (Tk_PhotoPutBlock_84_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL) || | ||||
|             ((TK_PHOTO_SET_SIZE_84 = | ||||
|                   (Tk_PhotoSetSize_84_t)_dfunc(lib, "Tk_PhotoSetSize")) == NULL)); | ||||
|     } | ||||
|     return ( | ||||
|         (TK_PHOTO_PUT_BLOCK_85 = | ||||
|              (Tk_PhotoPutBlock_85_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL); | ||||
|         (TK_PHOTO_PUT_BLOCK = | ||||
|              (Tk_PhotoPutBlock_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL); | ||||
| } | ||||
| 
 | ||||
| int | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user