bpo-32571: Avoid raising unneeded AttributeError and silencing it in C code (GH-5222)
Add two new private APIs: _PyObject_LookupAttr() and _PyObject_LookupAttrId()
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 9f3fd2d..717b56a 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -924,14 +924,10 @@
return -1;
/* Get the normalized named of the codec */
- res = _PyObject_GetAttrId(codec_info, &PyId_name);
- if (res == NULL) {
- if (PyErr_ExceptionMatches(PyExc_AttributeError))
- PyErr_Clear();
- else
- return -1;
+ if (_PyObject_LookupAttrId(codec_info, &PyId_name, &res) < 0) {
+ return -1;
}
- else if (PyUnicode_Check(res)) {
+ if (res != NULL && PyUnicode_Check(res)) {
const encodefuncentry *e = encodefuncs;
while (e->name != NULL) {
if (_PyUnicode_EqualToASCIIString(res, e->name)) {
@@ -1177,19 +1173,17 @@
if (Py_TYPE(buffer) == &PyBufferedReader_Type ||
Py_TYPE(buffer) == &PyBufferedWriter_Type ||
- Py_TYPE(buffer) == &PyBufferedRandom_Type) {
- raw = _PyObject_GetAttrId(buffer, &PyId_raw);
+ Py_TYPE(buffer) == &PyBufferedRandom_Type)
+ {
+ if (_PyObject_LookupAttrId(buffer, &PyId_raw, &raw) < 0)
+ goto error;
/* Cache the raw FileIO object to speed up 'closed' checks */
- if (raw == NULL) {
- if (PyErr_ExceptionMatches(PyExc_AttributeError))
- PyErr_Clear();
+ if (raw != NULL) {
+ if (Py_TYPE(raw) == &PyFileIO_Type)
+ self->raw = raw;
else
- goto error;
+ Py_DECREF(raw);
}
- else if (Py_TYPE(raw) == &PyFileIO_Type)
- self->raw = raw;
- else
- Py_DECREF(raw);
}
res = _PyObject_CallMethodId(buffer, &PyId_seekable, NULL);
@@ -1201,17 +1195,12 @@
goto error;
self->seekable = self->telling = r;
- res = _PyObject_GetAttrWithoutError(buffer, _PyIO_str_read1);
- if (res != NULL) {
- Py_DECREF(res);
- self->has_read1 = 1;
- }
- else if (!PyErr_Occurred()) {
- self->has_read1 = 0;
- }
- else {
+ r = _PyObject_LookupAttr(buffer, _PyIO_str_read1, &res);
+ if (r < 0) {
goto error;
}
+ Py_XDECREF(res);
+ self->has_read1 = r;
self->encoding_start_of_stream = 0;
if (_textiowrapper_fix_encoder_state(self) < 0) {
@@ -3020,10 +3009,9 @@
{
PyObject *res;
CHECK_ATTACHED(self);
- if (self->decoder == NULL)
- Py_RETURN_NONE;
- res = _PyObject_GetAttrWithoutError(self->decoder, _PyIO_str_newlines);
- if (res == NULL && !PyErr_Occurred()) {
+ if (self->decoder == NULL ||
+ _PyObject_LookupAttr(self->decoder, _PyIO_str_newlines, &res) == 0)
+ {
Py_RETURN_NONE;
}
return res;