◐ Shell
clean mode source ↗

Remove Dead Code in PyObject_Print

Bug report

While working on covering PyObject_Print, I noticed that I couldn't hit some lines with any test. Specifically, the part that checks the type of the representation of the object returned by PyObject_Str or PyObject_Repr:

PyObject *s;
if (flags & Py_PRINT_RAW)
s = PyObject_Str(op);
else
s = PyObject_Repr(op);
if (s == NULL)
ret = -1;
else if (PyBytes_Check(s)) {
fwrite(PyBytes_AS_STRING(s), 1,
PyBytes_GET_SIZE(s), fp);
}
else if (PyUnicode_Check(s)) {
PyObject *t;
t = PyUnicode_AsEncodedString(s, "utf-8", "backslashreplace");
if (t == NULL) {
ret = -1;
}
else {
fwrite(PyBytes_AS_STRING(t), 1,
PyBytes_GET_SIZE(t), fp);
Py_DECREF(t);
}
}
else {
PyErr_Format(PyExc_TypeError,
"str() or repr() returned '%.100s'",
Py_TYPE(s)->tp_name);
ret = -1;
}

As pointed out by @encukou, both aforementioned functions already check and ensure that the return type is a Python string:

if (!PyUnicode_Check(res)) {
_PyErr_Format(tstate, PyExc_TypeError,
"__str__ returned non-string (type %.200s)",
Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
}

if (!PyUnicode_Check(res)) {
_PyErr_Format(tstate, PyExc_TypeError,
"__repr__ returned non-string (type %.200s)",
Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
}

So it is possible to simplify the function by excluding the useless checks of types diffent from Python string.