Skip to content

Commit 0591364

Browse files
committed
gh-130821: Add type information to error messages for remaining magic methods
Add type information to error messages for __getnewargs__, __getnewargs_ex__, __hash__, and __init__ when they return the wrong type. This is a follow-up to GH-130835, which fixed similar inconsistencies for other magic methods. Error messages now use the format 'Type.__method__() must return ...' consistently, replacing the old format that used '%.200s' for type names and lacked the type prefix. Changes: - __getnewargs_ex__: 'should return' -> '%T.__getnewargs_ex__() must return' - __getnewargs__: 'should return' -> '%T.__getnewargs__() must return' - __hash__: '__hash__ method should return an integer' -> '%T.__hash__() must return an integer, not %T' - __init__: 'should return None' -> 'must return None' with %T format
1 parent 645f5c4 commit 0591364

6 files changed

Lines changed: 26 additions & 22 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add type information to error messages for ``__getnewargs__``,
2+
``__getnewargs_ex__``, ``__hash__``, and ``__init__`` when they return the wrong
3+
type. Error messages now use the format ``Type.__method__() must return ...``.

Modules/_testinternalcapi/test_cases.c.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/typeobject.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7908,15 +7908,15 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
79087908
}
79097909
if (!PyTuple_Check(newargs)) {
79107910
PyErr_Format(PyExc_TypeError,
7911-
"__getnewargs_ex__ should return a tuple, "
7912-
"not '%.200s'", Py_TYPE(newargs)->tp_name);
7911+
"%T.__getnewargs_ex__() must return a tuple, "
7912+
"not %T", obj, newargs);
79137913
Py_DECREF(newargs);
79147914
return -1;
79157915
}
79167916
if (PyTuple_GET_SIZE(newargs) != 2) {
79177917
PyErr_Format(PyExc_ValueError,
7918-
"__getnewargs_ex__ should return a tuple of "
7919-
"length 2, not %zd", PyTuple_GET_SIZE(newargs));
7918+
"%T.__getnewargs_ex__() must return a tuple of "
7919+
"length 2, not %zd", obj, PyTuple_GET_SIZE(newargs));
79207920
Py_DECREF(newargs);
79217921
return -1;
79227922
}
@@ -7928,17 +7928,17 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
79287928
if (!PyTuple_Check(*args)) {
79297929
PyErr_Format(PyExc_TypeError,
79307930
"first item of the tuple returned by "
7931-
"__getnewargs_ex__ must be a tuple, not '%.200s'",
7932-
Py_TYPE(*args)->tp_name);
7931+
"%T.__getnewargs_ex__() must be a tuple, not %T",
7932+
obj, *args);
79337933
Py_CLEAR(*args);
79347934
Py_CLEAR(*kwargs);
79357935
return -1;
79367936
}
79377937
if (!PyDict_Check(*kwargs)) {
79387938
PyErr_Format(PyExc_TypeError,
79397939
"second item of the tuple returned by "
7940-
"__getnewargs_ex__ must be a dict, not '%.200s'",
7941-
Py_TYPE(*kwargs)->tp_name);
7940+
"%T.__getnewargs_ex__() must be a dict, not %T",
7941+
obj, *kwargs);
79427942
Py_CLEAR(*args);
79437943
Py_CLEAR(*kwargs);
79447944
return -1;
@@ -7959,8 +7959,8 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
79597959
}
79607960
if (!PyTuple_Check(*args)) {
79617961
PyErr_Format(PyExc_TypeError,
7962-
"__getnewargs__ should return a tuple, "
7963-
"not '%.200s'", Py_TYPE(*args)->tp_name);
7962+
"%T.__getnewargs__() must return a tuple, "
7963+
"not %T", obj, *args);
79647964
Py_CLEAR(*args);
79657965
return -1;
79667966
}
@@ -10713,9 +10713,10 @@ slot_tp_hash(PyObject *self)
1071310713
return PyObject_HashNotImplemented(self);
1071410714
}
1071510715
if (!PyLong_Check(res)) {
10716+
PyErr_Format(PyExc_TypeError,
10717+
"%T.__hash__() must return an integer, not %T",
10718+
self, res);
1071610719
Py_DECREF(res);
10717-
PyErr_SetString(PyExc_TypeError,
10718-
"__hash__ method should return an integer");
1071910720
return -1;
1072010721
}
1072110722
/* Transform the PyLong `res` to a Py_hash_t `h`. For an existing
@@ -10975,8 +10976,8 @@ slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
1097510976
return -1;
1097610977
if (res != Py_None) {
1097710978
PyErr_Format(PyExc_TypeError,
10978-
"__init__() should return None, not '%.200s'",
10979-
Py_TYPE(res)->tp_name);
10979+
"%T.__init__() must return None, not %T",
10980+
self, res);
1098010981
Py_DECREF(res);
1098110982
return -1;
1098210983
}

Python/bytecodes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4251,8 +4251,8 @@ dummy_func(
42514251
inst(EXIT_INIT_CHECK, (should_be_none -- )) {
42524252
if (!PyStackRef_IsNone(should_be_none)) {
42534253
PyErr_Format(PyExc_TypeError,
4254-
"__init__() should return None, not '%.200s'",
4255-
Py_TYPE(PyStackRef_AsPyObjectBorrow(should_be_none))->tp_name);
4254+
"__init__() must return None, not %T",
4255+
PyStackRef_AsPyObjectBorrow(should_be_none));
42564256
ERROR_NO_POP();
42574257
}
42584258
DEAD(should_be_none);

Python/executor_cases.c.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)