Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate IptcImagePlugin helpers #7664

Merged
merged 3 commits into from
Jan 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions Tests/test_file_iptc.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,28 @@ def test_i():
c = b"a"

# Act
ret = IptcImagePlugin.i(c)
with pytest.warns(DeprecationWarning):
ret = IptcImagePlugin.i(c)

# Assert
assert ret == 97


def test_dump():
def test_dump(monkeypatch):
# Arrange
c = b"abc"
# Temporarily redirect stdout
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
mystdout = StringIO()
monkeypatch.setattr(sys, "stdout", mystdout)

# Act
IptcImagePlugin.dump(c)

# Reset stdout
sys.stdout = old_stdout
with pytest.warns(DeprecationWarning):
IptcImagePlugin.dump(c)

# Assert
assert mystdout.getvalue() == "61 62 63 \n"


def test_pad_deprecation():
with pytest.warns(DeprecationWarning):
assert IptcImagePlugin.PAD == b"\0\0\0\0"
11 changes: 11 additions & 0 deletions docs/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ ImageFile.raise_oserror
error codes returned by a codec's ``decode()`` method, which ImageFile already does
automatically.

IptcImageFile helper functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 10.2.0

The functions ``IptcImageFile.dump`` and ``IptcImageFile.i``, and the constant
``IptcImageFile.PAD`` have been deprecated and will be removed in Pillow
12.0.0 (2025-10-15). These are undocumented helper functions intended
for internal use, so there is no replacement. They can each be replaced
by a single line of code using builtin functions in Python.

Removed features
----------------

Expand Down
12 changes: 8 additions & 4 deletions docs/releasenotes/10.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ ImageFile.raise_oserror
error codes returned by a codec's ``decode()`` method, which ImageFile already does
automatically.

TODO
^^^^

TODO
IptcImageFile helper functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The functions ``IptcImageFile.dump`` and ``IptcImageFile.i``, and the constant
``IptcImageFile.PAD`` have been deprecated and will be removed in Pillow
12.0.0 (2025-10-15). These are undocumented helper functions intended
for internal use, so there is no replacement. They can each be replaced
by a single line of code using builtin functions in Python.

API Changes
===========
Expand Down
6 changes: 3 additions & 3 deletions src/PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -3190,7 +3190,7 @@ def _decompression_bomb_check(size):
)


def open(fp, mode="r", formats=None):
def open(fp, mode="r", formats=None) -> Image:
"""
Opens and identifies the given image file.

Expand Down Expand Up @@ -3415,7 +3415,7 @@ def merge(mode, bands):
# Plugin registry


def register_open(id, factory, accept=None):
def register_open(id, factory, accept=None) -> None:
"""
Register an image file plugin. This function should not be used
in application code.
Expand Down Expand Up @@ -3469,7 +3469,7 @@ def register_save_all(id, driver):
SAVE_ALL[id.upper()] = driver


def register_extension(id, extension):
def register_extension(id, extension) -> None:
"""
Registers an image extension. This function should not be
used in application code.
Expand Down
34 changes: 25 additions & 9 deletions src/PIL/IptcImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,45 @@

import os
import tempfile
from typing import Sequence

from . import Image, ImageFile
from ._binary import i16be as i16
from ._binary import i32be as i32
from ._deprecate import deprecate

COMPRESSION = {1: "raw", 5: "jpeg"}

PAD = b"\0\0\0\0"

def __getattr__(name: str) -> bytes:
if name == "PAD":
deprecate("IptcImagePlugin.PAD", 12)
return b"\0\0\0\0"
msg = f"module '{__name__}' has no attribute '{name}'"
raise AttributeError(msg)


#
# Helpers


def _i(c: bytes) -> int:
return i32((b"\0\0\0\0" + c)[-4:])


def _i8(c: int | bytes) -> int:
return c if isinstance(c, int) else c[0]


def i(c):
return i32((PAD + c)[-4:])
def i(c: bytes) -> int:
""".. deprecated:: 10.2.0"""
deprecate("IptcImagePlugin.i", 12)
return _i(c)


def dump(c):
def dump(c: Sequence[int | bytes]) -> None:
""".. deprecated:: 10.2.0"""
deprecate("IptcImagePlugin.dump", 12)
for i in c:
print("%02x" % _i8(i), end=" ")
print()
Expand All @@ -55,10 +71,10 @@
format = "IPTC"
format_description = "IPTC/NAA"

def getint(self, key):
return i(self.info[key])
def getint(self, key: tuple[int, int]) -> int:
return _i(self.info[key])

def field(self):
def field(self) -> tuple[tuple[int, int] | None, int]:
#
# get a IPTC field header
s = self.fp.read(5)
Expand All @@ -80,13 +96,13 @@
elif size == 128:
size = 0
elif size > 128:
size = i(self.fp.read(size - 128))
size = _i(self.fp.read(size - 128))

Check warning on line 99 in src/PIL/IptcImagePlugin.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/IptcImagePlugin.py#L99

Added line #L99 was not covered by tests
else:
size = i16(s, 3)

return tag, size

def _open(self):
def _open(self) -> None:
# load descriptive fields
while True:
offset = self.fp.tell()
Expand Down
Loading