Merge branch 'main' into include-dir-type-confusion

This commit is contained in:
Andrew Murray 2023-04-10 22:49:32 +10:00
commit 6fce7d6ed4
46 changed files with 349 additions and 760 deletions

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View 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}")

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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,
)

View File

@ -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]

View File

@ -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:

View File

@ -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,

View File

@ -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

View File

@ -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))

View File

@ -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]

View File

@ -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:

View File

@ -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)

View File

@ -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()

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

View File

@ -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):

View File

@ -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

View File

@ -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
~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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
^^^^^^^^^^^^

View File

@ -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.

View 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

View File

@ -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).

View File

@ -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

View File

@ -1,5 +1,5 @@
x.y.z
-----
xx.y.z
------
Backwards Incompatible Changes
==============================

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

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

View File

@ -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()
)

View File

@ -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

View File

@ -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,

View File

@ -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):

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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),

View File

@ -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):

View File

@ -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)

View File

@ -31,7 +31,6 @@ _plugins = [
"DdsImagePlugin",
"EpsImagePlugin",
"FitsImagePlugin",
"FitsStubImagePlugin",
"FliImagePlugin",
"FpxImagePlugin",
"FtexImagePlugin",

View File

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

View File

@ -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 */

View File

@ -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,17 +127,7 @@ 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(
TK_PHOTO_PUT_BLOCK(
interp,
photo,
&block,
@ -149,7 +136,6 @@ PyImagingPhotoPut(
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