diff --git a/docs/deprecations.rst b/docs/deprecations.rst index 0490ba439..29a7a62c2 100644 --- a/docs/deprecations.rst +++ b/docs/deprecations.rst @@ -193,6 +193,29 @@ Image.Image.get_child_images() method uses an image's file pointer, and so child images could only be retrieved from an :py:class:`PIL.ImageFile.ImageFile` instance. +ImageCms.ImageCmsProfile._set +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. deprecated:: 11.3.0 + +``ImageCms.ImageCmsProfile._set()`` has been deprecated, and will be removed in +Pillow 13 (2026-10-15). You should construct a new ``ImageCmsProfile`` instance +instead. + +ImageCms.ImageCmsProfile.product_name and .product_info +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. deprecated:: 11.3.0 + +``ImageCms.ImageCmsProfile.product_name`` and the corresponding +``.product_info`` attributes have been deprecated, and will be removed in +Pillow 13 (2026-10-15). These attributes can be accessed on the ``.profile`` +attribute of ``ImageCmsProfile`` instead. + +Note that ``.product_name`` and ``.product_info`` have been set to ``None`` on +``ImageCmsProfile`` since Pillow 2.3.0 (2014-01-01), so any working code that +makes use of this data will already access it on ``.profile``. + Removed features ---------------- diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index fdfbee789..d9a47aa9b 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -241,6 +241,9 @@ _FLAGS = { class ImageCmsProfile: + profile: core.CmsProfile + filename: str | None + def __init__(self, profile: str | SupportsRead[bytes] | core.CmsProfile) -> None: """ :param profile: Either a string representing a filename, @@ -248,6 +251,7 @@ class ImageCmsProfile: low-level profile object """ + self.filename = None if isinstance(profile, str): if sys.platform == "win32": @@ -256,22 +260,40 @@ class ImageCmsProfile: profile_bytes_path.decode("ascii") except UnicodeDecodeError: with open(profile, "rb") as f: - self._set(core.profile_frombytes(f.read())) + self.profile = core.profile_frombytes(f.read()) return - self._set(core.profile_open(profile), profile) + self.filename = profile + self.profile = core.profile_open(profile) elif hasattr(profile, "read"): - self._set(core.profile_frombytes(profile.read())) + self.profile = core.profile_frombytes(profile.read()) elif isinstance(profile, core.CmsProfile): - self._set(profile) + self.profile = profile else: msg = "Invalid type for Profile" # type: ignore[unreachable] raise TypeError(msg) + def __getattr__(self, attr: str) -> Any: + if attr in ("product_name", "product_info"): + deprecate( + f"ImageCms.ImageCmsProfile.{attr}", + 13, + action=( + f"Use ImageCms.ImageCmsProfile.profile.{attr} instead. " + f"Note that {attr} has been set to 'None' since Pillow 2.3.0." + ), + ) + return None + msg = f"'{self.__class__.__name__}' has no attribute '{attr}'" + raise AttributeError(msg) + def _set(self, profile: core.CmsProfile, filename: str | None = None) -> None: + deprecate( + "ImageCmsProfile._set", + 13, + action="Set the 'profile' and 'filename' attributes directly instead.", + ) self.profile = profile self.filename = filename - self.product_name = None # profile.product_name - self.product_info = None # profile.product_info def tobytes(self) -> bytes: """