Skip to content

Behaviour of unformattable ValueError on list.index has changed in Python 3.11 (change in PyErr_Format) #112768

Closed
@da-woods

Description

@da-woods

Bug report

Bug description:

lst = []

class C:
    def __repr__(self):
        raise RuntimeError("Oh no!")

try:
    lst.index(C())
except ValueError as e:
    print("This is good")
    print(repr(e))

On Python 3.10 this prints

This is good
ValueError()

On Python 3.11 this prints

Traceback (most recent call last):
  File "<path>", line 8, in <module>
    lst.index(C())
  File "<path>", line 5, in __repr__
    raise RuntimeError("Oh no!")
RuntimeError: Oh no!

When PyErr_Format fails in current versions of Python, it doesn't set the exception and instead raises the new one:

cpython/Python/errors.c

Lines 1162 to 1167 in 11d88a1

if (string != NULL) {
_PyErr_SetObject(tstate, exception, string);
Py_DECREF(string);
}
return NULL;
}

In earlier versions of Python it used to raise the requested exception unconditionally

cpython/Python/errors.c

Lines 1059 to 1064 in b6535ea

string = PyUnicode_FromFormatV(format, vargs);
_PyErr_SetObject(tstate, exception, string);
Py_XDECREF(string);
return NULL;
}

This looks to have been a deliberate change but it can affect the behaviour of real code (cython/cython#5894). Interestingly PyPy got there before you with this behaviour (https://foss.heptapod.net/pypy/pypy/-/issues/3978)

CPython versions tested on:

3.11

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.11only security fixes3.12only security fixes3.13bugs and security fixestype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions