diff --git a/Tests/test_image.py b/Tests/test_image.py index b326ca0f8..3fa071be1 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,6 +1,7 @@ import io import os import shutil +import sys import tempfile import pytest @@ -769,6 +770,20 @@ class TestImage: reloaded_exif.load(exif.tobytes()) assert reloaded_exif.get_ifd(0x8769) == exif.get_ifd(0x8769) + @pytest.mark.skipif( + sys.version_info < (3, 7), reason="Python 3.7 or greater required" + ) + 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 + @pytest.mark.parametrize( "test_module", [PIL, Image], diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 2e7abfb68..6f0fd1383 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -59,6 +59,16 @@ if sys.version_info >= (3, 7): if name == "PILLOW_VERSION": _raise_version_warning() return __version__ + else: + categories = {"NORMAL": 0, "SEQUENCE": 1, "CONTAINER": 2} + if name in categories: + warnings.warn( + "Image categories are deprecated and will be removed in Pillow 10 " + "(2023-01-02). Use is_animated instead.", + DeprecationWarning, + stacklevel=2, + ) + return categories[name] raise AttributeError(f"module '{__name__}' has no attribute '{name}'") @@ -69,6 +79,11 @@ else: # Silence warning assert PILLOW_VERSION + # categories + NORMAL = 0 + SEQUENCE = 1 + CONTAINER = 2 + logger = logging.getLogger(__name__) @@ -187,11 +202,6 @@ MAXCOVERAGE = 1 FASTOCTREE = 2 LIBIMAGEQUANT = 3 -# categories -NORMAL = 0 -SEQUENCE = 1 -CONTAINER = 2 - if hasattr(core, "DEFAULT_STRATEGY"): DEFAULT_STRATEGY = core.DEFAULT_STRATEGY FILTERED = core.FILTERED @@ -535,11 +545,22 @@ class Image: self._size = (0, 0) self.palette = None self.info = {} - self.category = NORMAL + self._category = 0 self.readonly = 0 self.pyaccess = None self._exif = None + def __getattr__(self, name): + if name == "category": + warnings.warn( + "Image categories are deprecated and will be removed in Pillow 10 " + "(2023-01-02). Use is_animated instead.", + DeprecationWarning, + stacklevel=2, + ) + return self._category + raise AttributeError(name) + @property def width(self): return self.size[0] @@ -648,7 +669,7 @@ class Image: and self.mode == other.mode and self.size == other.size and self.info == other.info - and self.category == other.category + and self._category == other._category and self.readonly == other.readonly and self.getpalette() == other.getpalette() and self.tobytes() == other.tobytes() diff --git a/src/PIL/MicImagePlugin.py b/src/PIL/MicImagePlugin.py index 2aed26030..9248b1b65 100644 --- a/src/PIL/MicImagePlugin.py +++ b/src/PIL/MicImagePlugin.py @@ -68,7 +68,7 @@ class MicImageFile(TiffImagePlugin.TiffImageFile): self.is_animated = self._n_frames > 1 if len(self.images) > 1: - self.category = Image.CONTAINER + self._category = Image.CONTAINER self.seek(0)