From 55469948282fe2dd763dcb8e66a767b5c63adb54 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 13 Aug 2024 19:03:14 +1000 Subject: [PATCH 1/7] Removed unnecessary variable --- Tests/test_file_webp_alpha.py | 2 +- Tests/test_file_webp_lossless.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/test_file_webp_alpha.py b/Tests/test_file_webp_alpha.py index 53cdfff0327..c88fe3589ea 100644 --- a/Tests/test_file_webp_alpha.py +++ b/Tests/test_file_webp_alpha.py @@ -13,7 +13,7 @@ hopper, ) -_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed") +pytest.importorskip("PIL._webp", reason="WebP support not installed") def test_read_rgba() -> None: diff --git a/Tests/test_file_webp_lossless.py b/Tests/test_file_webp_lossless.py index dc98ad3f013..80429715e9e 100644 --- a/Tests/test_file_webp_lossless.py +++ b/Tests/test_file_webp_lossless.py @@ -8,7 +8,7 @@ from .helper import assert_image_equal, hopper -_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed") +pytest.importorskip("PIL._webp", reason="WebP support not installed") RGB_MODE = "RGB" From f3aec6dd383bb27676e7e02a7749a5bff1cc30c2 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 13 Aug 2024 19:05:32 +1000 Subject: [PATCH 2/7] Simplified code --- setup.py | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/setup.py b/setup.py index edfa9ee28fc..863d102cf85 100644 --- a/setup.py +++ b/setup.py @@ -794,25 +794,17 @@ def build_extensions(self): if feature.want("webp"): _dbg("Looking for webp") if all( - _find_include_file(self, src) - for src in [ - "webp/encode.h", - "webp/decode.h", - "webp/mux.h", - "webp/demux.h", - ] + _find_include_file(self, "webp/" + include) + for include in ("encode.h", "decode.h", "mux.h", "demux.h") ): - # In Google's precompiled zip it is call "libwebp": - if all( - _find_library_file(self, lib) - for lib in ["webp", "webpmux", "webpdemux"] - ): - feature.webp = "webp" - elif all( - _find_library_file(self, lib) - for lib in ["libwebp", "libwebpmux", "libwebpdemux"] - ): - feature.webp = "libwebp" + # In Google's precompiled zip it is called "libwebp" + for prefix in ("", "lib"): + if all( + _find_library_file(self, prefix + library) + for library in ("webp", "webpmux", "webpdemux") + ): + feature.webp = prefix + "webp" + break if feature.want("xcb"): _dbg("Looking for xcb") @@ -901,12 +893,8 @@ def build_extensions(self): self._remove_extension("PIL._imagingcms") if feature.webp: - libs = [ - feature.webp, - feature.webp + "mux", - feature.webp + "demux", - ] - self._update_extension("PIL._webp", libs, []) + libs = [feature.webp, feature.webp + "mux", feature.webp + "demux"] + self._update_extension("PIL._webp", libs) else: self._remove_extension("PIL._webp") From c7e6289b36d4eb1823b6bfcace27674826a58e43 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 13 Aug 2024 19:07:01 +1000 Subject: [PATCH 3/7] Use relative import --- src/PIL/features.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PIL/features.py b/src/PIL/features.py index 9421dbd3cf4..e505adae060 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -7,9 +7,9 @@ from typing import IO import PIL -from PIL import _deprecate from . import Image +from ._deprecate import deprecate modules = { "pil": ("PIL._imaging", "PILLOW_VERSION"), @@ -149,7 +149,7 @@ def check_feature(feature: str) -> bool | None: try: imported_module = __import__(module, fromlist=["PIL"]) if isinstance(flag, bool): - _deprecate.deprecate(f'check_feature("{feature}")', 12) + deprecate(f'check_feature("{feature}")', 12) return flag return getattr(imported_module, flag) except ModuleNotFoundError: From ba82dff7bc6c489f299a63d2f2d3722dfe11852e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 13 Aug 2024 19:10:54 +1000 Subject: [PATCH 4/7] Updated test name --- Tests/test_file_webp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 6e9eea4aec0..6ccd489bb47 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -166,7 +166,7 @@ def test_WebPEncode_with_invalid_args(self) -> None: with pytest.raises(TypeError): _webp.WebPEncode() - def test_WebPDecode_with_invalid_args(self) -> None: + def test_WebPAnimDecoder_with_invalid_args(self) -> None: """ Calling decoder functions with no arguments should result in an error. """ From 66319fcce764f4f09e53900b2896ec15457f691f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 13 Aug 2024 19:17:36 +1000 Subject: [PATCH 5/7] Animation support is no longer conditionally enabled --- src/_webp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_webp.c b/src/_webp.c index 306a290bdb9..d1943b3e0a5 100644 --- a/src/_webp.c +++ b/src/_webp.c @@ -11,7 +11,7 @@ * Check the versions from mux.h and demux.h, to ensure the WebPAnimEncoder and * WebPAnimDecoder APIs are present (initial support was added in 0.5.0). The * very early versions had some significant differences, so we require later - * versions, before enabling animation support. + * versions. */ #if WEBP_MUX_ABI_VERSION < 0x0106 || WEBP_DEMUX_ABI_VERSION < 0x0107 #error libwebp 0.5.0 and above is required. Upgrade libwebp or build Pillow with --disable-webp flag From 45552b5b4f6ea470639e5c7ff0d9efb96ad7db68 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 13 Aug 2024 19:24:34 +1000 Subject: [PATCH 6/7] Updated documentation --- docs/deprecations.rst | 10 ++++++++++ docs/releasenotes/11.0.0.rst | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/deprecations.rst b/docs/deprecations.rst index 058468cfe36..a9498d5ed5e 100644 --- a/docs/deprecations.rst +++ b/docs/deprecations.rst @@ -126,6 +126,16 @@ JpegImageFile.huffman_ac and JpegImageFile.huffman_dc The ``huffman_ac`` and ``huffman_dc`` dictionaries on JPEG images were unused. They have been deprecated, and will be removed in Pillow 12 (2025-10-15). +Specific WebP Feature Checks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. deprecated:: 11.0.0 + +``features.check("transp_webp")``, ``features.check("webp_mux")`` and +``features.check("webp_anim")`` are now deprecated. They will always return +``True`` if the WebP module is installed, until they are removed in Pillow +12.0.0 (2025-10-15). + Removed features ---------------- diff --git a/docs/releasenotes/11.0.0.rst b/docs/releasenotes/11.0.0.rst index bb707a04480..ac9237acf78 100644 --- a/docs/releasenotes/11.0.0.rst +++ b/docs/releasenotes/11.0.0.rst @@ -61,10 +61,10 @@ have been deprecated, and will be removed in Pillow 12 (2025-10-15). Specific WebP Feature Checks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following features ``features.check("transp_webp")``, -``features.check("webp_mux")``, and ``features.check("webp_anim")`` are now -always ``True`` if the WebP module is installed and should not be used. -These checks will be removed in Pillow 12.0.0 (2025-10-15). +``features.check("transp_webp")``, ``features.check("webp_mux")`` and +``features.check("webp_anim")`` are now deprecated. They will always return +``True`` if the WebP module is installed, until they are removed in Pillow +12.0.0 (2025-10-15). API Changes =========== From 359d7592c7861729092434154d131310c7bf1d71 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 14 Aug 2024 18:41:39 +1000 Subject: [PATCH 7/7] Test deprecation warnings --- Tests/test_features.py | 21 ++++++++++++++++----- src/PIL/features.py | 12 +++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Tests/test_features.py b/Tests/test_features.py index cb8fd8688c9..80778284773 100644 --- a/Tests/test_features.py +++ b/Tests/test_features.py @@ -18,7 +18,11 @@ def test_check() -> None: for codec in features.codecs: assert features.check_codec(codec) == features.check(codec) for feature in features.features: - assert features.check_feature(feature) == features.check(feature) + if "webp" in feature: + with pytest.warns(DeprecationWarning): + assert features.check_feature(feature) == features.check(feature) + else: + assert features.check_feature(feature) == features.check(feature) def test_version() -> None: @@ -43,19 +47,26 @@ def test(name: str, function: Callable[[str], str | None]) -> None: for codec in features.codecs: test(codec, features.version_codec) for feature in features.features: - test(feature, features.version_feature) + if "webp" in feature: + with pytest.warns(DeprecationWarning): + test(feature, features.version_feature) + else: + test(feature, features.version_feature) def test_webp_transparency() -> None: - assert features.check("transp_webp") == features.check_module("webp") + with pytest.warns(DeprecationWarning): + assert features.check("transp_webp") == features.check_module("webp") def test_webp_mux() -> None: - assert features.check("webp_mux") == features.check_module("webp") + with pytest.warns(DeprecationWarning): + assert features.check("webp_mux") == features.check_module("webp") def test_webp_anim() -> None: - assert features.check("webp_anim") == features.check_module("webp") + with pytest.warns(DeprecationWarning): + assert features.check("webp_anim") == features.check_module("webp") @skip_unless_feature("libjpeg_turbo") diff --git a/src/PIL/features.py b/src/PIL/features.py index e505adae060..24c5ee978b3 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -180,7 +180,17 @@ def get_supported_features() -> list[str]: """ :returns: A list of all supported features. """ - return [f for f in features if check_feature(f)] + supported_features = [] + for f, (module, flag, _) in features.items(): + if flag is True: + for feature, (feature_module, _) in modules.items(): + if feature_module == module: + if check_module(feature): + supported_features.append(f) + break + elif check_feature(f): + supported_features.append(f) + return supported_features def check(feature: str) -> bool | None: