pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/f320be77ffb73e3b9e7fc98c37b8df3975d84b40

b48faa60c69660fa.css" /> bpo-32571: Avoid raising unneeded AttributeError and silencing it in… · python/cpython@f320be7 · GitHub
Skip to content

Commit f320be7

Browse files
serhiy-storchakamethane
authored andcommitted
bpo-32571: Avoid raising unneeded AttributeError and silencing it in C code (GH-5222)
Add two new private APIs: _PyObject_LookupAttr() and _PyObject_LookupAttrId()
1 parent 2b822a0 commit f320be7

22 files changed

Lines changed: 1443 additions & 1430 deletions

Include/object.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,11 +536,20 @@ PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *);
536536
PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *);
537537
#ifndef Py_LIMITED_API
538538
PyAPI_FUNC(int) _PyObject_IsAbstract(PyObject *);
539-
/* Same as PyObject_GetAttr(), but don't raise AttributeError. */
540-
PyAPI_FUNC(PyObject *) _PyObject_GetAttrWithoutError(PyObject *, PyObject *);
541539
PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, struct _Py_Identifier *);
542540
PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObject *);
543541
PyAPI_FUNC(int) _PyObject_HasAttrId(PyObject *, struct _Py_Identifier *);
542+
/* Replacements of PyObject_GetAttr() and _PyObject_GetAttrId() which
543+
don't raise AttributeError.
544+
545+
Return 1 and set *result != NULL if an attribute is found.
546+
Return 0 and set *result == NULL if an attribute is not found;
547+
an AttributeError is silenced.
548+
Return -1 and set *result == NULL if an error other than AttributeError
549+
is raised.
550+
*/
551+
PyAPI_FUNC(int) _PyObject_LookupAttr(PyObject *, PyObject *, PyObject **);
552+
PyAPI_FUNC(int) _PyObject_LookupAttrId(PyObject *, struct _Py_Identifier *, PyObject **);
544553
PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *);
545554
#endif
546555
PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *);

Modules/_collectionsmodule.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,12 +1339,10 @@ deque_reduce(dequeobject *deque)
13391339
PyObject *dict, *it;
13401340
_Py_IDENTIFIER(__dict__);
13411341

1342-
dict = _PyObject_GetAttrId((PyObject *)deque, &PyId___dict__);
1342+
if (_PyObject_LookupAttrId((PyObject *)deque, &PyId___dict__, &dict) < 0) {
1343+
return NULL;
1344+
}
13431345
if (dict == NULL) {
1344-
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
1345-
return NULL;
1346-
}
1347-
PyErr_Clear();
13481346
dict = Py_None;
13491347
Py_INCREF(dict);
13501348
}

Modules/_io/bufferedio.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,7 +1541,9 @@ _bufferedreader_read_all(buffered *self)
15411541
}
15421542
_bufferedreader_reset_buf(self);
15431543

1544-
readall = _PyObject_GetAttrWithoutError(self->raw, _PyIO_str_readall);
1544+
if (_PyObject_LookupAttr(self->raw, _PyIO_str_readall, &readall) < 0) {
1545+
goto cleanup;
1546+
}
15451547
if (readall) {
15461548
tmp = _PyObject_CallNoArg(readall);
15471549
Py_DECREF(readall);
@@ -1561,9 +1563,6 @@ _bufferedreader_read_all(buffered *self)
15611563
}
15621564
goto cleanup;
15631565
}
1564-
else if (PyErr_Occurred()) {
1565-
goto cleanup;
1566-
}
15671566

15681567
chunks = PyList_New(0);
15691568
if (chunks == NULL)

Modules/_io/fileio.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,12 +1073,10 @@ fileio_repr(fileio *self)
10731073
if (self->fd < 0)
10741074
return PyUnicode_FromFormat("<_io.FileIO [closed]>");
10751075

1076-
nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
1076+
if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) {
1077+
return NULL;
1078+
}
10771079
if (nameobj == NULL) {
1078-
if (PyErr_ExceptionMatches(PyExc_AttributeError))
1079-
PyErr_Clear();
1080-
else
1081-
return NULL;
10821080
res = PyUnicode_FromFormat(
10831081
"<_io.FileIO fd=%d mode='%s' closefd=%s>",
10841082
self->fd, mode_string(self), self->closefd ? "True" : "False");

Modules/_io/iobase.c

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,12 @@ static int
133133
iobase_is_closed(PyObject *self)
134134
{
135135
PyObject *res;
136+
int ret;
136137
/* This gets the derived attribute, which is *not* __IOBase_closed
137138
in most cases! */
138-
res = _PyObject_GetAttrId(self, &PyId___IOBase_closed);
139-
if (res == NULL) {
140-
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
141-
return -1;
142-
}
143-
PyErr_Clear();
144-
return 0;
145-
}
146-
Py_DECREF(res);
147-
return 1;
139+
ret = _PyObject_LookupAttrId(self, &PyId___IOBase_closed, &res);
140+
Py_XDECREF(res);
141+
return ret;
148142
}
149143

150144
/* Flush and close methods */
@@ -190,20 +184,16 @@ iobase_check_closed(PyObject *self)
190184
int closed;
191185
/* This gets the derived attribute, which is *not* __IOBase_closed
192186
in most cases! */
193-
res = _PyObject_GetAttrWithoutError(self, _PyIO_str_closed);
194-
if (res == NULL) {
195-
if (PyErr_Occurred()) {
187+
closed = _PyObject_LookupAttr(self, _PyIO_str_closed, &res);
188+
if (closed > 0) {
189+
closed = PyObject_IsTrue(res);
190+
Py_DECREF(res);
191+
if (closed > 0) {
192+
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
196193
return -1;
197194
}
198-
return 0;
199-
}
200-
closed = PyObject_IsTrue(res);
201-
Py_DECREF(res);
202-
if (closed <= 0) {
203-
return closed;
204195
}
205-
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
206-
return -1;
196+
return closed;
207197
}
208198

209199
PyObject *
@@ -273,8 +263,7 @@ iobase_finalize(PyObject *self)
273263

274264
/* If `closed` doesn't exist or can't be evaluated as bool, then the
275265
object is probably in an unusable state, so ignore. */
276-
res = _PyObject_GetAttrWithoutError(self, _PyIO_str_closed);
277-
if (res == NULL) {
266+
if (_PyObject_LookupAttr(self, _PyIO_str_closed, &res) <= 0) {
278267
PyErr_Clear();
279268
closed = -1;
280269
}
@@ -538,8 +527,7 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
538527
PyObject *peek, *buffer, *result;
539528
Py_ssize_t old_size = -1;
540529

541-
peek = _PyObject_GetAttrWithoutError(self, _PyIO_str_peek);
542-
if (peek == NULL && PyErr_Occurred()) {
530+
if (_PyObject_LookupAttr(self, _PyIO_str_peek, &peek) < 0) {
543531
return NULL;
544532
}
545533

Modules/_io/textio.c

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -924,14 +924,10 @@ _textiowrapper_set_encoder(textio *self, PyObject *codec_info,
924924
return -1;
925925

926926
/* Get the normalized named of the codec */
927-
res = _PyObject_GetAttrId(codec_info, &PyId_name);
928-
if (res == NULL) {
929-
if (PyErr_ExceptionMatches(PyExc_AttributeError))
930-
PyErr_Clear();
931-
else
932-
return -1;
927+
if (_PyObject_LookupAttrId(codec_info, &PyId_name, &res) < 0) {
928+
return -1;
933929
}
934-
else if (PyUnicode_Check(res)) {
930+
if (res != NULL && PyUnicode_Check(res)) {
935931
const encodefuncentry *e = encodefuncs;
936932
while (e->name != NULL) {
937933
if (_PyUnicode_EqualToASCIIString(res, e->name)) {
@@ -1177,19 +1173,17 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11771173

11781174
if (Py_TYPE(buffer) == &PyBufferedReader_Type ||
11791175
Py_TYPE(buffer) == &PyBufferedWriter_Type ||
1180-
Py_TYPE(buffer) == &PyBufferedRandom_Type) {
1181-
raw = _PyObject_GetAttrId(buffer, &PyId_raw);
1176+
Py_TYPE(buffer) == &PyBufferedRandom_Type)
1177+
{
1178+
if (_PyObject_LookupAttrId(buffer, &PyId_raw, &raw) < 0)
1179+
goto error;
11821180
/* Cache the raw FileIO object to speed up 'closed' checks */
1183-
if (raw == NULL) {
1184-
if (PyErr_ExceptionMatches(PyExc_AttributeError))
1185-
PyErr_Clear();
1181+
if (raw != NULL) {
1182+
if (Py_TYPE(raw) == &PyFileIO_Type)
1183+
self->raw = raw;
11861184
else
1187-
goto error;
1185+
Py_DECREF(raw);
11881186
}
1189-
else if (Py_TYPE(raw) == &PyFileIO_Type)
1190-
self->raw = raw;
1191-
else
1192-
Py_DECREF(raw);
11931187
}
11941188

11951189
res = _PyObject_CallMethodId(buffer, &PyId_seekable, NULL);
@@ -1201,17 +1195,12 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
12011195
goto error;
12021196
self->seekable = self->telling = r;
12031197

1204-
res = _PyObject_GetAttrWithoutError(buffer, _PyIO_str_read1);
1205-
if (res != NULL) {
1206-
Py_DECREF(res);
1207-
self->has_read1 = 1;
1208-
}
1209-
else if (!PyErr_Occurred()) {
1210-
self->has_read1 = 0;
1211-
}
1212-
else {
1198+
r = _PyObject_LookupAttr(buffer, _PyIO_str_read1, &res);
1199+
if (r < 0) {
12131200
goto error;
12141201
}
1202+
Py_XDECREF(res);
1203+
self->has_read1 = r;
12151204

12161205
self->encoding_start_of_stream = 0;
12171206
if (_textiowrapper_fix_encoder_state(self) < 0) {
@@ -3020,10 +3009,9 @@ textiowrapper_newlines_get(textio *self, void *context)
30203009
{
30213010
PyObject *res;
30223011
CHECK_ATTACHED(self);
3023-
if (self->decoder == NULL)
3024-
Py_RETURN_NONE;
3025-
res = _PyObject_GetAttrWithoutError(self->decoder, _PyIO_str_newlines);
3026-
if (res == NULL && !PyErr_Occurred()) {
3012+
if (self->decoder == NULL ||
3013+
_PyObject_LookupAttr(self->decoder, _PyIO_str_newlines, &res) == 0)
3014+
{
30273015
Py_RETURN_NONE;
30283016
}
30293017
return res;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy