Skip to content

Inspect arg as Python object, instead of using PyErr_Clear()#9726

Open
radarhere wants to merge 5 commits into
python-pillow:mainfrom
radarhere:clear
Open

Inspect arg as Python object, instead of using PyErr_Clear()#9726
radarhere wants to merge 5 commits into
python-pillow:mainfrom
radarhere:clear

Conversation

@radarhere

@radarhere radarhere commented Jun 28, 2026

Copy link
Copy Markdown
Member

In _convert_transparent(), instead of failing a call to PyArg_ParseTuple(), calling PyErr_Clear() afterwards and then trying again,

Pillow/src/_imaging.c

Lines 1084 to 1089 in 095bbc3

if (PyArg_ParseTuple(args, "s(iii)", &mode_name, &r, &g, &b)) {
const ModeID mode = findModeID(mode_name);
return PyImagingNew(ImagingConvertTransparent(self->image, mode, r, g, b));
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "si", &mode_name, &r)) {

an alternative strategy would be to parse the second argument as a PyObject ("O") and then check if it is a tuple or not.

A similar change could be made in _convert_matrix().

Comment thread src/_imaging.c Outdated
if (!PyArg_ParseTuple(args, "sO", &mode_name, &matrix)) {
return NULL;
}
if (PyTuple_Size(matrix) == 12) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails with lists:

from PIL import Image

rgb = Image.new("RGB", (8, 8), (255, 0, 0))


def transparent(t):
    rgb.info["transparency"] = t
    return rgb.convert("RGBA")


cases = {
    "matrix tuple(4)": lambda: rgb.convert("L", matrix=(0.3, 0.59, 0.11, 0.0)),
    "matrix list(4)": lambda: rgb.convert("L", matrix=[0.3, 0.59, 0.11, 0.0]),
    "matrix tuple(12)": lambda: rgb.convert("RGB", matrix=tuple(range(12))),
    "matrix list(12)": lambda: rgb.convert("RGB", matrix=list(range(12))),
    "transparency tuple": lambda: transparent((255, 0, 0)),
    "transparency list": lambda: transparent([255, 0, 0]),
}

for label, fn in cases.items():
    try:
        fn()
        print(f"OK    {label}")
    except Exception as e:
        print(f"RAISE {label}: {type(e).__name__}: {e}")

Before:

OK    matrix tuple(4)
OK    matrix list(4)
OK    matrix tuple(12)
OK    matrix list(12)
OK    transparency tuple
OK    transparency list

After:

OK    matrix tuple(4)
RAISE matrix list(4): SystemError: <method 'convert_matrix' of 'ImagingCore' objects> returned a result with an exception set
OK    matrix tuple(12)
RAISE matrix list(12): SystemError: /Users/nad/build_macos_installer/installer/variant/binaries/build_source/Objects/tupleobject.c:96: bad argument to internal function
OK    transparency tuple
RAISE transparency list: TypeError: 'list' object cannot be interpreted as an integer

Maybe worth adding a test?

Suggested change
if (PyTuple_Size(matrix) == 12) {
if (PySequence_Size(matrix) == 12) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matrix should be a tuple?

Pillow/src/PIL/Image.py

Lines 1017 to 1020 in 9c9fece

def convert(
self,
mode: str | None = None,
matrix: tuple[float, ...] | None = None,

Pillow/src/PIL/Image.py

Lines 1054 to 1055 in 9c9fece

:param matrix: An optional conversion matrix. If given, this
should be 4- or 12-tuple containing floating point values.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should according to type hint and docstring, but not enforced.

There is existing code using lists:

https://github.com/search?q=%2F%5C.convert%5C%28.*%2C+matrix%3D%5C%5B%2F&type=code

Do we want to change the behaviour in this PR?

Comment thread src/_imaging.c Outdated
radarhere and others added 2 commits June 30, 2026 13:54
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
@codspeed-hq

codspeed-hq Bot commented Jun 30, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 331 untouched benchmarks


Comparing radarhere:clear (9197939) with main (6590b1b)

Open in CodSpeed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants