bpo-32571: Avoid raising unneeded AttributeError and silencing it in C code (GH-5222)

Add two new private APIs: _PyObject_LookupAttr() and _PyObject_LookupAttrId()
This commit is contained in:
Serhiy Storchaka 2018-01-25 10:49:40 +02:00 committed by INADA Naoki
parent 2b822a0bb1
commit f320be77ff
22 changed files with 1455 additions and 1442 deletions

View File

@ -536,11 +536,20 @@ PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *);
PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *); PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *);
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(int) _PyObject_IsAbstract(PyObject *); PyAPI_FUNC(int) _PyObject_IsAbstract(PyObject *);
/* Same as PyObject_GetAttr(), but don't raise AttributeError. */
PyAPI_FUNC(PyObject *) _PyObject_GetAttrWithoutError(PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, struct _Py_Identifier *); PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, struct _Py_Identifier *);
PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObject *); PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObject *);
PyAPI_FUNC(int) _PyObject_HasAttrId(PyObject *, struct _Py_Identifier *); PyAPI_FUNC(int) _PyObject_HasAttrId(PyObject *, struct _Py_Identifier *);
/* Replacements of PyObject_GetAttr() and _PyObject_GetAttrId() which
don't raise AttributeError.
Return 1 and set *result != NULL if an attribute is found.
Return 0 and set *result == NULL if an attribute is not found;
an AttributeError is silenced.
Return -1 and set *result == NULL if an error other than AttributeError
is raised.
*/
PyAPI_FUNC(int) _PyObject_LookupAttr(PyObject *, PyObject *, PyObject **);
PyAPI_FUNC(int) _PyObject_LookupAttrId(PyObject *, struct _Py_Identifier *, PyObject **);
PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *); PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *);
#endif #endif
PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *); PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *);

View File

@ -1339,12 +1339,10 @@ deque_reduce(dequeobject *deque)
PyObject *dict, *it; PyObject *dict, *it;
_Py_IDENTIFIER(__dict__); _Py_IDENTIFIER(__dict__);
dict = _PyObject_GetAttrId((PyObject *)deque, &PyId___dict__); if (_PyObject_LookupAttrId((PyObject *)deque, &PyId___dict__, &dict) < 0) {
return NULL;
}
if (dict == NULL) { if (dict == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return NULL;
}
PyErr_Clear();
dict = Py_None; dict = Py_None;
Py_INCREF(dict); Py_INCREF(dict);
} }

View File

@ -1541,7 +1541,9 @@ _bufferedreader_read_all(buffered *self)
} }
_bufferedreader_reset_buf(self); _bufferedreader_reset_buf(self);
readall = _PyObject_GetAttrWithoutError(self->raw, _PyIO_str_readall); if (_PyObject_LookupAttr(self->raw, _PyIO_str_readall, &readall) < 0) {
goto cleanup;
}
if (readall) { if (readall) {
tmp = _PyObject_CallNoArg(readall); tmp = _PyObject_CallNoArg(readall);
Py_DECREF(readall); Py_DECREF(readall);
@ -1561,9 +1563,6 @@ _bufferedreader_read_all(buffered *self)
} }
goto cleanup; goto cleanup;
} }
else if (PyErr_Occurred()) {
goto cleanup;
}
chunks = PyList_New(0); chunks = PyList_New(0);
if (chunks == NULL) if (chunks == NULL)

View File

@ -1073,12 +1073,10 @@ fileio_repr(fileio *self)
if (self->fd < 0) if (self->fd < 0)
return PyUnicode_FromFormat("<_io.FileIO [closed]>"); return PyUnicode_FromFormat("<_io.FileIO [closed]>");
nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) {
return NULL;
}
if (nameobj == NULL) { if (nameobj == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
else
return NULL;
res = PyUnicode_FromFormat( res = PyUnicode_FromFormat(
"<_io.FileIO fd=%d mode='%s' closefd=%s>", "<_io.FileIO fd=%d mode='%s' closefd=%s>",
self->fd, mode_string(self), self->closefd ? "True" : "False"); self->fd, mode_string(self), self->closefd ? "True" : "False");

View File

@ -133,18 +133,12 @@ static int
iobase_is_closed(PyObject *self) iobase_is_closed(PyObject *self)
{ {
PyObject *res; PyObject *res;
int ret;
/* This gets the derived attribute, which is *not* __IOBase_closed /* This gets the derived attribute, which is *not* __IOBase_closed
in most cases! */ in most cases! */
res = _PyObject_GetAttrId(self, &PyId___IOBase_closed); ret = _PyObject_LookupAttrId(self, &PyId___IOBase_closed, &res);
if (res == NULL) { Py_XDECREF(res);
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { return ret;
return -1;
}
PyErr_Clear();
return 0;
}
Py_DECREF(res);
return 1;
} }
/* Flush and close methods */ /* Flush and close methods */
@ -190,20 +184,16 @@ iobase_check_closed(PyObject *self)
int closed; int closed;
/* This gets the derived attribute, which is *not* __IOBase_closed /* This gets the derived attribute, which is *not* __IOBase_closed
in most cases! */ in most cases! */
res = _PyObject_GetAttrWithoutError(self, _PyIO_str_closed); closed = _PyObject_LookupAttr(self, _PyIO_str_closed, &res);
if (res == NULL) { if (closed > 0) {
if (PyErr_Occurred()) { closed = PyObject_IsTrue(res);
Py_DECREF(res);
if (closed > 0) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
return -1; return -1;
} }
return 0;
} }
closed = PyObject_IsTrue(res); return closed;
Py_DECREF(res);
if (closed <= 0) {
return closed;
}
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
return -1;
} }
PyObject * PyObject *
@ -273,8 +263,7 @@ iobase_finalize(PyObject *self)
/* If `closed` doesn't exist or can't be evaluated as bool, then the /* If `closed` doesn't exist or can't be evaluated as bool, then the
object is probably in an unusable state, so ignore. */ object is probably in an unusable state, so ignore. */
res = _PyObject_GetAttrWithoutError(self, _PyIO_str_closed); if (_PyObject_LookupAttr(self, _PyIO_str_closed, &res) <= 0) {
if (res == NULL) {
PyErr_Clear(); PyErr_Clear();
closed = -1; closed = -1;
} }
@ -538,8 +527,7 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
PyObject *peek, *buffer, *result; PyObject *peek, *buffer, *result;
Py_ssize_t old_size = -1; Py_ssize_t old_size = -1;
peek = _PyObject_GetAttrWithoutError(self, _PyIO_str_peek); if (_PyObject_LookupAttr(self, _PyIO_str_peek, &peek) < 0) {
if (peek == NULL && PyErr_Occurred()) {
return NULL; return NULL;
} }

View File

@ -924,14 +924,10 @@ _textiowrapper_set_encoder(textio *self, PyObject *codec_info,
return -1; return -1;
/* Get the normalized named of the codec */ /* Get the normalized named of the codec */
res = _PyObject_GetAttrId(codec_info, &PyId_name); if (_PyObject_LookupAttrId(codec_info, &PyId_name, &res) < 0) {
if (res == NULL) { return -1;
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
else
return -1;
} }
else if (PyUnicode_Check(res)) { if (res != NULL && PyUnicode_Check(res)) {
const encodefuncentry *e = encodefuncs; const encodefuncentry *e = encodefuncs;
while (e->name != NULL) { while (e->name != NULL) {
if (_PyUnicode_EqualToASCIIString(res, e->name)) { if (_PyUnicode_EqualToASCIIString(res, e->name)) {
@ -1177,19 +1173,17 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
if (Py_TYPE(buffer) == &PyBufferedReader_Type || if (Py_TYPE(buffer) == &PyBufferedReader_Type ||
Py_TYPE(buffer) == &PyBufferedWriter_Type || Py_TYPE(buffer) == &PyBufferedWriter_Type ||
Py_TYPE(buffer) == &PyBufferedRandom_Type) { Py_TYPE(buffer) == &PyBufferedRandom_Type)
raw = _PyObject_GetAttrId(buffer, &PyId_raw); {
if (_PyObject_LookupAttrId(buffer, &PyId_raw, &raw) < 0)
goto error;
/* Cache the raw FileIO object to speed up 'closed' checks */ /* Cache the raw FileIO object to speed up 'closed' checks */
if (raw == NULL) { if (raw != NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) if (Py_TYPE(raw) == &PyFileIO_Type)
PyErr_Clear(); self->raw = raw;
else 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); res = _PyObject_CallMethodId(buffer, &PyId_seekable, NULL);
@ -1201,17 +1195,12 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
goto error; goto error;
self->seekable = self->telling = r; self->seekable = self->telling = r;
res = _PyObject_GetAttrWithoutError(buffer, _PyIO_str_read1); r = _PyObject_LookupAttr(buffer, _PyIO_str_read1, &res);
if (res != NULL) { if (r < 0) {
Py_DECREF(res);
self->has_read1 = 1;
}
else if (!PyErr_Occurred()) {
self->has_read1 = 0;
}
else {
goto error; goto error;
} }
Py_XDECREF(res);
self->has_read1 = r;
self->encoding_start_of_stream = 0; self->encoding_start_of_stream = 0;
if (_textiowrapper_fix_encoder_state(self) < 0) { if (_textiowrapper_fix_encoder_state(self) < 0) {
@ -3020,10 +3009,9 @@ textiowrapper_newlines_get(textio *self, void *context)
{ {
PyObject *res; PyObject *res;
CHECK_ATTACHED(self); CHECK_ATTACHED(self);
if (self->decoder == NULL) if (self->decoder == NULL ||
Py_RETURN_NONE; _PyObject_LookupAttr(self->decoder, _PyIO_str_newlines, &res) == 0)
res = _PyObject_GetAttrWithoutError(self->decoder, _PyIO_str_newlines); {
if (res == NULL && !PyErr_Occurred()) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
return res; return res;

View File

@ -367,18 +367,15 @@ init_method_ref(PyObject *self, _Py_Identifier *name,
PyObject **method_func, PyObject **method_self) PyObject **method_func, PyObject **method_self)
{ {
PyObject *func, *func2; PyObject *func, *func2;
int ret;
/* *method_func and *method_self should be consistent. All refcount decrements /* *method_func and *method_self should be consistent. All refcount decrements
should be occurred after setting *method_self and *method_func. */ should be occurred after setting *method_self and *method_func. */
func = _PyObject_GetAttrId(self, name); ret = _PyObject_LookupAttrId(self, name, &func);
if (func == NULL) { if (func == NULL) {
*method_self = NULL; *method_self = NULL;
Py_CLEAR(*method_func); Py_CLEAR(*method_func);
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { return ret;
return -1;
}
PyErr_Clear();
return 0;
} }
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) == self) { if (PyMethod_Check(func) && PyMethod_GET_SELF(func) == self) {
@ -1155,11 +1152,12 @@ _Pickler_SetOutputStream(PicklerObject *self, PyObject *file)
{ {
_Py_IDENTIFIER(write); _Py_IDENTIFIER(write);
assert(file != NULL); assert(file != NULL);
self->write = _PyObject_GetAttrId(file, &PyId_write); if (_PyObject_LookupAttrId(file, &PyId_write, &self->write) < 0) {
return -1;
}
if (self->write == NULL) { if (self->write == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_SetString(PyExc_TypeError,
PyErr_SetString(PyExc_TypeError, "file must have a 'write' attribute");
"file must have a 'write' attribute");
return -1; return -1;
} }
@ -1504,19 +1502,16 @@ _Unpickler_SetInputStream(UnpicklerObject *self, PyObject *file)
_Py_IDENTIFIER(read); _Py_IDENTIFIER(read);
_Py_IDENTIFIER(readline); _Py_IDENTIFIER(readline);
self->peek = _PyObject_GetAttrId(file, &PyId_peek); if (_PyObject_LookupAttrId(file, &PyId_peek, &self->peek) < 0) {
if (self->peek == NULL) { return -1;
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
else
return -1;
} }
self->read = _PyObject_GetAttrId(file, &PyId_read); (void)_PyObject_LookupAttrId(file, &PyId_read, &self->read);
self->readline = _PyObject_GetAttrId(file, &PyId_readline); (void)_PyObject_LookupAttrId(file, &PyId_readline, &self->readline);
if (self->readline == NULL || self->read == NULL) { if (self->readline == NULL || self->read == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"file must have 'read' and 'readline' attributes"); "file must have 'read' and 'readline' attributes");
}
Py_CLEAR(self->read); Py_CLEAR(self->read);
Py_CLEAR(self->readline); Py_CLEAR(self->readline);
Py_CLEAR(self->peek); Py_CLEAR(self->peek);
@ -1691,7 +1686,7 @@ get_deep_attribute(PyObject *obj, PyObject *names, PyObject **pparent)
PyObject *name = PyList_GET_ITEM(names, i); PyObject *name = PyList_GET_ITEM(names, i);
Py_XDECREF(parent); Py_XDECREF(parent);
parent = obj; parent = obj;
obj = PyObject_GetAttr(parent, name); (void)_PyObject_LookupAttr(parent, name, &obj);
if (obj == NULL) { if (obj == NULL) {
Py_DECREF(parent); Py_DECREF(parent);
return NULL; return NULL;
@ -1704,16 +1699,6 @@ get_deep_attribute(PyObject *obj, PyObject *names, PyObject **pparent)
return obj; return obj;
} }
static void
reformat_attribute_error(PyObject *obj, PyObject *name)
{
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
PyErr_Format(PyExc_AttributeError,
"Can't get attribute %R on %R", name, obj);
}
}
static PyObject * static PyObject *
getattribute(PyObject *obj, PyObject *name, int allow_qualname) getattribute(PyObject *obj, PyObject *name, int allow_qualname)
@ -1727,10 +1712,13 @@ getattribute(PyObject *obj, PyObject *name, int allow_qualname)
attr = get_deep_attribute(obj, dotted_path, NULL); attr = get_deep_attribute(obj, dotted_path, NULL);
Py_DECREF(dotted_path); Py_DECREF(dotted_path);
} }
else else {
attr = PyObject_GetAttr(obj, name); (void)_PyObject_LookupAttr(obj, name, &attr);
if (attr == NULL) }
reformat_attribute_error(obj, name); if (attr == NULL && !PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError,
"Can't get attribute %R on %R", name, obj);
}
return attr; return attr;
} }
@ -1748,9 +1736,6 @@ _checkmodule(PyObject *module_name, PyObject *module,
PyObject *candidate = get_deep_attribute(module, dotted_path, NULL); PyObject *candidate = get_deep_attribute(module, dotted_path, NULL);
if (candidate == NULL) { if (candidate == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
return -1; return -1;
} }
if (candidate != global) { if (candidate != global) {
@ -1772,14 +1757,10 @@ whichmodule(PyObject *global, PyObject *dotted_path)
_Py_IDENTIFIER(modules); _Py_IDENTIFIER(modules);
_Py_IDENTIFIER(__main__); _Py_IDENTIFIER(__main__);
module_name = _PyObject_GetAttrId(global, &PyId___module__); if (_PyObject_LookupAttrId(global, &PyId___module__, &module_name) < 0) {
return NULL;
if (module_name == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
PyErr_Clear();
} }
else { if (module_name) {
/* In some rare cases (e.g., bound methods of extension types), /* In some rare cases (e.g., bound methods of extension types),
__module__ can be None. If it is so, then search sys.modules for __module__ can be None. If it is so, then search sys.modules for
the module of global. */ the module of global. */
@ -3328,12 +3309,8 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
global_name = name; global_name = name;
} }
else { else {
global_name = _PyObject_GetAttrId(obj, &PyId___qualname__); if (_PyObject_LookupAttrId(obj, &PyId___qualname__, &global_name) < 0)
if (global_name == NULL) { goto error;
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
goto error;
PyErr_Clear();
}
if (global_name == NULL) { if (global_name == NULL) {
global_name = _PyObject_GetAttrId(obj, &PyId___name__); global_name = _PyObject_GetAttrId(obj, &PyId___name__);
if (global_name == NULL) if (global_name == NULL)
@ -3656,13 +3633,9 @@ get_class(PyObject *obj)
PyObject *cls; PyObject *cls;
_Py_IDENTIFIER(__class__); _Py_IDENTIFIER(__class__);
cls = _PyObject_GetAttrId(obj, &PyId___class__); if (_PyObject_LookupAttrId(obj, &PyId___class__, &cls) == 0) {
if (cls == NULL) { cls = (PyObject *) Py_TYPE(obj);
if (PyErr_ExceptionMatches(PyExc_AttributeError)) { Py_INCREF(cls);
PyErr_Clear();
cls = (PyObject *) Py_TYPE(obj);
Py_INCREF(cls);
}
} }
return cls; return cls;
} }
@ -3734,14 +3707,10 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
PyObject *name; PyObject *name;
_Py_IDENTIFIER(__name__); _Py_IDENTIFIER(__name__);
name = _PyObject_GetAttrId(callable, &PyId___name__); if (_PyObject_LookupAttrId(callable, &PyId___name__, &name) < 0) {
if (name == NULL) { return -1;
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return -1;
}
PyErr_Clear();
} }
else if (PyUnicode_Check(name)) { if (name != NULL && PyUnicode_Check(name)) {
_Py_IDENTIFIER(__newobj_ex__); _Py_IDENTIFIER(__newobj_ex__);
use_newobj_ex = _PyUnicode_EqualToASCIIId( use_newobj_ex = _PyUnicode_EqualToASCIIId(
name, &PyId___newobj_ex__); name, &PyId___newobj_ex__);
@ -4108,7 +4077,9 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
don't actually have to check for a __reduce__ method. */ don't actually have to check for a __reduce__ method. */
/* Check for a __reduce_ex__ method. */ /* Check for a __reduce_ex__ method. */
reduce_func = _PyObject_GetAttrId(obj, &PyId___reduce_ex__); if (_PyObject_LookupAttrId(obj, &PyId___reduce_ex__, &reduce_func) < 0) {
goto error;
}
if (reduce_func != NULL) { if (reduce_func != NULL) {
PyObject *proto; PyObject *proto;
proto = PyLong_FromLong(self->proto); proto = PyLong_FromLong(self->proto);
@ -4119,12 +4090,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
else { else {
PickleState *st = _Pickle_GetGlobalState(); PickleState *st = _Pickle_GetGlobalState();
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
else {
goto error;
}
/* Check for a __reduce__ method. */ /* Check for a __reduce__ method. */
reduce_func = _PyObject_GetAttrId(obj, &PyId___reduce__); reduce_func = _PyObject_GetAttrId(obj, &PyId___reduce__);
if (reduce_func != NULL) { if (reduce_func != NULL) {
@ -4401,13 +4366,9 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file,
return -1; return -1;
} }
self->dispatch_table = _PyObject_GetAttrId((PyObject *)self, if (_PyObject_LookupAttrId((PyObject *)self,
&PyId_dispatch_table); &PyId_dispatch_table, &self->dispatch_table) < 0) {
if (self->dispatch_table == NULL) { return -1;
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return -1;
}
PyErr_Clear();
} }
return 0; return 0;
@ -5370,12 +5331,11 @@ instantiate(PyObject *cls, PyObject *args)
if (!PyTuple_GET_SIZE(args) && PyType_Check(cls)) { if (!PyTuple_GET_SIZE(args) && PyType_Check(cls)) {
_Py_IDENTIFIER(__getinitargs__); _Py_IDENTIFIER(__getinitargs__);
_Py_IDENTIFIER(__new__); _Py_IDENTIFIER(__new__);
PyObject *func = _PyObject_GetAttrId(cls, &PyId___getinitargs__); PyObject *func;
if (_PyObject_LookupAttrId(cls, &PyId___getinitargs__, &func) < 0) {
return NULL;
}
if (func == NULL) { if (func == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return NULL;
}
PyErr_Clear();
return _PyObject_CallMethodIdObjArgs(cls, &PyId___new__, cls, NULL); return _PyObject_CallMethodIdObjArgs(cls, &PyId___new__, cls, NULL);
} }
Py_DECREF(func); Py_DECREF(func);
@ -6225,16 +6185,11 @@ load_build(UnpicklerObject *self)
inst = self->stack->data[Py_SIZE(self->stack) - 1]; inst = self->stack->data[Py_SIZE(self->stack) - 1];
setstate = _PyObject_GetAttrId(inst, &PyId___setstate__); if (_PyObject_LookupAttrId(inst, &PyId___setstate__, &setstate) < 0) {
if (setstate == NULL) { Py_DECREF(state);
if (PyErr_ExceptionMatches(PyExc_AttributeError)) return -1;
PyErr_Clear();
else {
Py_DECREF(state);
return -1;
}
} }
else { if (setstate != NULL) {
PyObject *result; PyObject *result;
/* The explicit __setstate__ is responsible for everything. */ /* The explicit __setstate__ is responsible for everything. */

View File

@ -2203,11 +2203,10 @@ array_array___reduce_ex__(arrayobject *self, PyObject *value)
if (protocol == -1 && PyErr_Occurred()) if (protocol == -1 && PyErr_Occurred())
return NULL; return NULL;
dict = _PyObject_GetAttrId((PyObject *)self, &PyId___dict__); if (_PyObject_LookupAttrId((PyObject *)self, &PyId___dict__, &dict) < 0) {
return NULL;
}
if (dict == NULL) { if (dict == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
PyErr_Clear();
dict = Py_None; dict = Py_None;
Py_INCREF(dict); Py_INCREF(dict);
} }

View File

@ -830,17 +830,15 @@ tee(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
copyfunc = _PyObject_GetAttrId(it, &PyId___copy__); if (_PyObject_LookupAttrId(it, &PyId___copy__, &copyfunc) < 0) {
if (copyfunc != NULL) {
copyable = it;
}
else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
Py_DECREF(it); Py_DECREF(it);
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
} }
if (copyfunc != NULL) {
copyable = it;
}
else { else {
PyErr_Clear();
copyable = tee_fromiterable(it); copyable = tee_fromiterable(it);
Py_DECREF(it); Py_DECREF(it);
if (copyable == NULL) { if (copyable == NULL) {

View File

@ -171,16 +171,14 @@ PyObject_GetItem(PyObject *o, PyObject *key)
if (PyType_Check(o)) { if (PyType_Check(o)) {
PyObject *meth, *result, *stack[1] = {key}; PyObject *meth, *result, *stack[1] = {key};
_Py_IDENTIFIER(__class_getitem__); _Py_IDENTIFIER(__class_getitem__);
meth = _PyObject_GetAttrId(o, &PyId___class_getitem__); if (_PyObject_LookupAttrId(o, &PyId___class_getitem__, &meth) < 0) {
return NULL;
}
if (meth) { if (meth) {
result = _PyObject_FastCall(meth, stack, 1); result = _PyObject_FastCall(meth, stack, 1);
Py_DECREF(meth); Py_DECREF(meth);
return result; return result;
} }
else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return NULL;
}
PyErr_Clear();
} }
return type_error("'%.200s' object is not subscriptable", o); return type_error("'%.200s' object is not subscriptable", o);
@ -2268,14 +2266,9 @@ abstract_get_bases(PyObject *cls)
PyObject *bases; PyObject *bases;
Py_ALLOW_RECURSION Py_ALLOW_RECURSION
bases = _PyObject_GetAttrId(cls, &PyId___bases__); (void)_PyObject_LookupAttrId(cls, &PyId___bases__, &bases);
Py_END_ALLOW_RECURSION Py_END_ALLOW_RECURSION
if (bases == NULL) { if (bases != NULL && !PyTuple_Check(bases)) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
return NULL;
}
if (!PyTuple_Check(bases)) {
Py_DECREF(bases); Py_DECREF(bases);
return NULL; return NULL;
} }
@ -2338,26 +2331,23 @@ static int
recursive_isinstance(PyObject *inst, PyObject *cls) recursive_isinstance(PyObject *inst, PyObject *cls)
{ {
PyObject *icls; PyObject *icls;
int retval = 0; int retval;
_Py_IDENTIFIER(__class__); _Py_IDENTIFIER(__class__);
if (PyType_Check(cls)) { if (PyType_Check(cls)) {
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls); retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
if (retval == 0) { if (retval == 0) {
PyObject *c = _PyObject_GetAttrId(inst, &PyId___class__); retval = _PyObject_LookupAttrId(inst, &PyId___class__, &icls);
if (c == NULL) { if (icls != NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) if (icls != (PyObject *)(inst->ob_type) && PyType_Check(icls)) {
PyErr_Clear();
else
retval = -1;
}
else {
if (c != (PyObject *)(inst->ob_type) &&
PyType_Check(c))
retval = PyType_IsSubtype( retval = PyType_IsSubtype(
(PyTypeObject *)c, (PyTypeObject *)icls,
(PyTypeObject *)cls); (PyTypeObject *)cls);
Py_DECREF(c); }
else {
retval = 0;
}
Py_DECREF(icls);
} }
} }
} }
@ -2365,14 +2355,8 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
if (!check_class(cls, if (!check_class(cls,
"isinstance() arg 2 must be a type or tuple of types")) "isinstance() arg 2 must be a type or tuple of types"))
return -1; return -1;
icls = _PyObject_GetAttrId(inst, &PyId___class__); retval = _PyObject_LookupAttrId(inst, &PyId___class__, &icls);
if (icls == NULL) { if (icls != NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
else
retval = -1;
}
else {
retval = abstract_issubclass(icls, cls); retval = abstract_issubclass(icls, cls);
Py_DECREF(icls); Py_DECREF(icls);
} }

View File

@ -246,21 +246,14 @@ method_repr(PyMethodObject *a)
{ {
PyObject *self = a->im_self; PyObject *self = a->im_self;
PyObject *func = a->im_func; PyObject *func = a->im_func;
PyObject *funcname = NULL, *result = NULL; PyObject *funcname, *result;
const char *defname = "?"; const char *defname = "?";
funcname = _PyObject_GetAttrId(func, &PyId___qualname__); if (_PyObject_LookupAttrId(func, &PyId___qualname__, &funcname) < 0 ||
if (funcname == NULL) { (funcname == NULL &&
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) _PyObject_LookupAttrId(func, &PyId___name__, &funcname) < 0))
return NULL; {
PyErr_Clear(); return NULL;
funcname = _PyObject_GetAttrId(func, &PyId___name__);
if (funcname == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
PyErr_Clear();
}
} }
if (funcname != NULL && !PyUnicode_Check(funcname)) { if (funcname != NULL && !PyUnicode_Check(funcname)) {
@ -542,7 +535,7 @@ static PyObject *
instancemethod_repr(PyObject *self) instancemethod_repr(PyObject *self)
{ {
PyObject *func = PyInstanceMethod_Function(self); PyObject *func = PyInstanceMethod_Function(self);
PyObject *funcname = NULL , *result = NULL; PyObject *funcname, *result;
const char *defname = "?"; const char *defname = "?";
if (func == NULL) { if (func == NULL) {
@ -550,13 +543,10 @@ instancemethod_repr(PyObject *self)
return NULL; return NULL;
} }
funcname = _PyObject_GetAttrId(func, &PyId___name__); if (_PyObject_LookupAttrId(func, &PyId___name__, &funcname) < 0) {
if (funcname == NULL) { return NULL;
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
PyErr_Clear();
} }
else if (!PyUnicode_Check(funcname)) { if (funcname != NULL && !PyUnicode_Check(funcname)) {
Py_DECREF(funcname); Py_DECREF(funcname);
funcname = NULL; funcname = NULL;
} }

View File

@ -2234,17 +2234,16 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
} }
else if (arg != NULL) { else if (arg != NULL) {
_Py_IDENTIFIER(keys); _Py_IDENTIFIER(keys);
PyObject *func = _PyObject_GetAttrId(arg, &PyId_keys); PyObject *func;
if (func != NULL) { if (_PyObject_LookupAttrId(arg, &PyId_keys, &func) < 0) {
result = -1;
}
else if (func != NULL) {
Py_DECREF(func); Py_DECREF(func);
result = PyDict_Merge(self, arg, 1); result = PyDict_Merge(self, arg, 1);
} }
else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
result = PyDict_MergeFromSeq2(self, arg, 1);
}
else { else {
result = -1; result = PyDict_MergeFromSeq2(self, arg, 1);
} }
} }

View File

@ -352,13 +352,11 @@ gen_close_iter(PyObject *yf)
return -1; return -1;
} }
else { else {
PyObject *meth = _PyObject_GetAttrId(yf, &PyId_close); PyObject *meth;
if (meth == NULL) { if (_PyObject_LookupAttrId(yf, &PyId_close, &meth) < 0) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_WriteUnraisable(yf);
PyErr_WriteUnraisable(yf);
PyErr_Clear();
} }
else { if (meth) {
retval = _PyObject_CallNoArg(meth); retval = _PyObject_CallNoArg(meth);
Py_DECREF(meth); Py_DECREF(meth);
if (retval == NULL) if (retval == NULL)
@ -471,13 +469,12 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
gen->gi_running = 0; gen->gi_running = 0;
} else { } else {
/* `yf` is an iterator or a coroutine-like object. */ /* `yf` is an iterator or a coroutine-like object. */
PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw); PyObject *meth;
if (_PyObject_LookupAttrId(yf, &PyId_throw, &meth) < 0) {
Py_DECREF(yf);
return NULL;
}
if (meth == NULL) { if (meth == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
Py_DECREF(yf);
return NULL;
}
PyErr_Clear();
Py_DECREF(yf); Py_DECREF(yf);
goto throw_here; goto throw_here;
} }

View File

@ -817,16 +817,11 @@ _PyObject_IsAbstract(PyObject *obj)
if (obj == NULL) if (obj == NULL)
return 0; return 0;
isabstract = _PyObject_GetAttrId(obj, &PyId___isabstractmethod__); res = _PyObject_LookupAttrId(obj, &PyId___isabstractmethod__, &isabstract);
if (isabstract == NULL) { if (res > 0) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) { res = PyObject_IsTrue(isabstract);
PyErr_Clear(); Py_DECREF(isabstract);
return 0;
}
return -1;
} }
res = PyObject_IsTrue(isabstract);
Py_DECREF(isabstract);
return res; return res;
} }
@ -888,47 +883,74 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
return NULL; return NULL;
} }
PyObject * int
_PyObject_GetAttrWithoutError(PyObject *v, PyObject *name) _PyObject_LookupAttr(PyObject *v, PyObject *name, PyObject **result)
{ {
PyTypeObject *tp = Py_TYPE(v); PyTypeObject *tp = Py_TYPE(v);
PyObject *ret = NULL;
if (!PyUnicode_Check(name)) { if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'", "attribute name must be string, not '%.200s'",
name->ob_type->tp_name); name->ob_type->tp_name);
return NULL; *result = NULL;
return -1;
} }
if (tp->tp_getattro == PyObject_GenericGetAttr) { if (tp->tp_getattro == PyObject_GenericGetAttr) {
return _PyObject_GenericGetAttrWithDict(v, name, NULL, 1); *result = _PyObject_GenericGetAttrWithDict(v, name, NULL, 1);
if (*result != NULL) {
return 1;
}
if (PyErr_Occurred()) {
return -1;
}
return 0;
} }
if (tp->tp_getattro != NULL) { if (tp->tp_getattro != NULL) {
ret = (*tp->tp_getattro)(v, name); *result = (*tp->tp_getattro)(v, name);
} }
else if (tp->tp_getattr != NULL) { else if (tp->tp_getattr != NULL) {
const char *name_str = PyUnicode_AsUTF8(name); const char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL) if (name_str == NULL) {
return NULL; *result = NULL;
ret = (*tp->tp_getattr)(v, (char *)name_str); return -1;
}
*result = (*tp->tp_getattr)(v, (char *)name_str);
} }
if (ret == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { if (*result != NULL) {
PyErr_Clear(); return 1;
} }
return ret; if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return -1;
}
PyErr_Clear();
return 0;
}
int
_PyObject_LookupAttrId(PyObject *v, _Py_Identifier *name, PyObject **result)
{
PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
if (!oname) {
*result = NULL;
return -1;
}
return _PyObject_LookupAttr(v, oname, result);
} }
int int
PyObject_HasAttr(PyObject *v, PyObject *name) PyObject_HasAttr(PyObject *v, PyObject *name)
{ {
PyObject *res = _PyObject_GetAttrWithoutError(v, name); PyObject *res;
if (res != NULL) { if (_PyObject_LookupAttr(v, name, &res) < 0) {
Py_DECREF(res); PyErr_Clear();
return 1; return 0;
} }
PyErr_Clear(); if (res == NULL) {
return 0; return 0;
}
Py_DECREF(res);
return 1;
} }
int int

View File

@ -2359,7 +2359,10 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
goto handle_kwargs; goto handle_kwargs;
} }
func = _PyObject_GetAttrId(other, &PyId_keys); if (_PyObject_LookupAttrId(other, &PyId_keys, &func) < 0) {
Py_DECREF(other);
return NULL;
}
if (func != NULL) { if (func != NULL) {
PyObject *keys, *iterator, *key; PyObject *keys, *iterator, *key;
keys = _PyObject_CallNoArg(func); keys = _PyObject_CallNoArg(func);
@ -2391,15 +2394,11 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL; return NULL;
goto handle_kwargs; goto handle_kwargs;
} }
else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
if (_PyObject_LookupAttrId(other, &PyId_items, &func) < 0) {
Py_DECREF(other); Py_DECREF(other);
return NULL; return NULL;
} }
else {
PyErr_Clear();
}
func = _PyObject_GetAttrId(other, &PyId_items);
if (func != NULL) { if (func != NULL) {
PyObject *items; PyObject *items;
Py_DECREF(other); Py_DECREF(other);
@ -2413,13 +2412,6 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL; return NULL;
goto handle_kwargs; goto handle_kwargs;
} }
else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
Py_DECREF(other);
return NULL;
}
else {
PyErr_Clear();
}
res = mutablemapping_add_pairs(self, other); res = mutablemapping_add_pairs(self, other);
Py_DECREF(other); Py_DECREF(other);

View File

@ -2403,7 +2403,9 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
if (PyType_Check(tmp)) { if (PyType_Check(tmp)) {
continue; continue;
} }
tmp = _PyObject_GetAttrId(tmp, &PyId___mro_entries__); if (_PyObject_LookupAttrId(tmp, &PyId___mro_entries__, &tmp) < 0) {
return NULL;
}
if (tmp != NULL) { if (tmp != NULL) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"type() doesn't support MRO entry resolution; " "type() doesn't support MRO entry resolution; "
@ -2411,12 +2413,6 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
Py_DECREF(tmp); Py_DECREF(tmp);
return NULL; return NULL;
} }
else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
else {
return NULL;
}
} }
/* Search the bases for the proper metatype to deal with this: */ /* Search the bases for the proper metatype to deal with this: */
winner = _PyType_CalculateMetaclass(metatype, bases); winner = _PyType_CalculateMetaclass(metatype, bases);
@ -4099,15 +4095,12 @@ _PyObject_GetState(PyObject *obj, int required)
PyObject *getstate; PyObject *getstate;
_Py_IDENTIFIER(__getstate__); _Py_IDENTIFIER(__getstate__);
getstate = _PyObject_GetAttrId(obj, &PyId___getstate__); if (_PyObject_LookupAttrId(obj, &PyId___getstate__, &getstate) < 0) {
return NULL;
}
if (getstate == NULL) { if (getstate == NULL) {
PyObject *slotnames; PyObject *slotnames;
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return NULL;
}
PyErr_Clear();
if (required && obj->ob_type->tp_itemsize) { if (required && obj->ob_type->tp_itemsize) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"can't pickle %.200s objects", "can't pickle %.200s objects",
@ -4174,14 +4167,12 @@ _PyObject_GetState(PyObject *obj, int required)
name = PyList_GET_ITEM(slotnames, i); name = PyList_GET_ITEM(slotnames, i);
Py_INCREF(name); Py_INCREF(name);
value = PyObject_GetAttr(obj, name); if (_PyObject_LookupAttr(obj, name, &value) < 0) {
goto error;
}
if (value == NULL) { if (value == NULL) {
Py_DECREF(name); Py_DECREF(name);
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
goto error;
}
/* It is not an error if the attribute is not present. */ /* It is not an error if the attribute is not present. */
PyErr_Clear();
} }
else { else {
int err = PyDict_SetItem(slots, name, value); int err = PyDict_SetItem(slots, name, value);

View File

@ -497,11 +497,27 @@ class Obj2ModVisitor(PickleVisitor):
def visitField(self, field, name, sum=None, prod=None, depth=0): def visitField(self, field, name, sum=None, prod=None, depth=0):
ctype = get_c_type(field.type) ctype = get_c_type(field.type)
self.emit("if (_PyObject_LookupAttrId(obj, &PyId_%s, &tmp) < 0) {" % field.name, depth)
self.emit("return 1;", depth+1)
self.emit("}", depth)
if not field.opt: if not field.opt:
self.emit("tmp = _PyObject_GetAttrId(obj, &PyId_%s);" % field.name, depth) self.emit("if (tmp == NULL) {", depth)
message = "required field \\\"%s\\\" missing from %s" % (field.name, name)
format = "PyErr_SetString(PyExc_TypeError, \"%s\");"
self.emit(format % message, depth+1, reflow=False)
self.emit("return 1;", depth+1)
else: else:
self.emit("tmp = get_not_none(obj, &PyId_%s);" % field.name, depth) self.emit("if (tmp == NULL || tmp == Py_None) {", depth)
self.emit("if (tmp != NULL) {", depth) self.emit("Py_CLEAR(tmp);", depth+1)
if self.isNumeric(field):
self.emit("%s = 0;" % field.name, depth+1)
elif not self.isSimpleType(field):
self.emit("%s = NULL;" % field.name, depth+1)
else:
raise TypeError("could not determine the default value for %s" % field.name)
self.emit("}", depth)
self.emit("else {", depth)
self.emit("int res;", depth+1) self.emit("int res;", depth+1)
if field.seq: if field.seq:
self.emit("Py_ssize_t len;", depth+1) self.emit("Py_ssize_t len;", depth+1)
@ -539,25 +555,6 @@ class Obj2ModVisitor(PickleVisitor):
self.emit("if (res != 0) goto failed;", depth+1) self.emit("if (res != 0) goto failed;", depth+1)
self.emit("Py_CLEAR(tmp);", depth+1) self.emit("Py_CLEAR(tmp);", depth+1)
if not field.opt:
self.emit("} else {", depth)
self.emit("if (PyErr_ExceptionMatches(PyExc_AttributeError)) {", depth+1)
message = "required field \\\"%s\\\" missing from %s" % (field.name, name)
format = "PyErr_SetString(PyExc_TypeError, \"%s\");"
self.emit(format % message, depth+2, reflow=False)
self.emit("}", depth+1)
self.emit("return 1;", depth+1)
else:
self.emit("} else if (PyErr_Occurred()) {", depth)
self.emit("return 1;", depth+1)
self.emit("} else {", depth)
if self.isNumeric(field):
self.emit("%s = 0;" % field.name, depth+1)
elif not self.isSimpleType(field):
self.emit("%s = NULL;" % field.name, depth+1)
else:
raise TypeError("could not determine the default value for %s" % field.name)
self.emit("}", depth) self.emit("}", depth)
@ -662,18 +659,14 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
Py_ssize_t i, numfields = 0; Py_ssize_t i, numfields = 0;
int res = -1; int res = -1;
PyObject *key, *value, *fields; PyObject *key, *value, *fields;
fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields); if (_PyObject_LookupAttrId((PyObject*)Py_TYPE(self), &PyId__fields, &fields) < 0) {
goto cleanup;
}
if (fields) { if (fields) {
numfields = PySequence_Size(fields); numfields = PySequence_Size(fields);
if (numfields == -1) if (numfields == -1)
goto cleanup; goto cleanup;
} }
else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
else {
goto cleanup;
}
res = 0; /* if no error occurs, this stays 0 to the end */ res = 0; /* if no error occurs, this stays 0 to the end */
if (numfields < PyTuple_GET_SIZE(args)) { if (numfields < PyTuple_GET_SIZE(args)) {
@ -713,19 +706,13 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
static PyObject * static PyObject *
ast_type_reduce(PyObject *self, PyObject *unused) ast_type_reduce(PyObject *self, PyObject *unused)
{ {
PyObject *res;
_Py_IDENTIFIER(__dict__); _Py_IDENTIFIER(__dict__);
PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__); PyObject *dict;
if (dict == NULL) { if (_PyObject_LookupAttrId(self, &PyId___dict__, &dict) < 0) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) return NULL;
PyErr_Clear();
else
return NULL;
} }
if (dict) { if (dict) {
res = Py_BuildValue("O()O", Py_TYPE(self), dict); return Py_BuildValue("O()N", Py_TYPE(self), dict);
Py_DECREF(dict);
return res;
} }
return Py_BuildValue("O()", Py_TYPE(self)); return Py_BuildValue("O()", Py_TYPE(self));
} }
@ -965,22 +952,6 @@ static int add_ast_fields(void)
return 0; return 0;
} }
static PyObject *get_not_none(PyObject *obj, _Py_Identifier *id)
{
PyObject *attr = _PyObject_GetAttrId(obj, id);
if (!attr) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
return NULL;
}
else if (attr == Py_None) {
Py_DECREF(attr);
return NULL;
}
return attr;
}
""", 0, reflow=False) """, 0, reflow=False)
self.emit("static int init_types(void)",0) self.emit("static int init_types(void)",0)

File diff suppressed because it is too large Load Diff

View File

@ -80,11 +80,8 @@ get_warnings_attr(_Py_Identifier *attr_id, int try_import)
return NULL; return NULL;
} }
obj = _PyObject_GetAttrId(warnings_module, attr_id); (void)_PyObject_LookupAttrId(warnings_module, attr_id, &obj);
Py_DECREF(warnings_module); Py_DECREF(warnings_module);
if (obj == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
return obj; return obj;
} }
@ -893,13 +890,10 @@ get_source_line(PyObject *module_globals, int lineno)
Py_INCREF(module_name); Py_INCREF(module_name);
/* Make sure the loader implements the optional get_source() method. */ /* Make sure the loader implements the optional get_source() method. */
get_source = _PyObject_GetAttrId(loader, &PyId_get_source); (void)_PyObject_LookupAttrId(loader, &PyId_get_source, &get_source);
Py_DECREF(loader); Py_DECREF(loader);
if (!get_source) { if (!get_source) {
Py_DECREF(module_name); Py_DECREF(module_name);
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
}
return NULL; return NULL;
} }
/* Call get_source() to get the source code. */ /* Call get_source() to get the source code. */

View File

@ -71,12 +71,10 @@ update_bases(PyObject *bases, PyObject *const *args, Py_ssize_t nargs)
} }
continue; continue;
} }
meth = _PyObject_GetAttrId(base, &PyId___mro_entries__); if (_PyObject_LookupAttrId(base, &PyId___mro_entries__, &meth) < 0) {
goto error;
}
if (!meth) { if (!meth) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
goto error;
}
PyErr_Clear();
if (new_bases) { if (new_bases) {
if (PyList_Append(new_bases, base) < 0) { if (PyList_Append(new_bases, base) < 0) {
goto error; goto error;
@ -218,18 +216,11 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
} }
/* else: meta is not a class, so we cannot do the metaclass /* else: meta is not a class, so we cannot do the metaclass
calculation, so we will use the explicitly given object as it is */ calculation, so we will use the explicitly given object as it is */
prep = _PyObject_GetAttrId(meta, &PyId___prepare__); if (_PyObject_LookupAttrId(meta, &PyId___prepare__, &prep) < 0) {
if (prep == NULL) { ns = NULL;
if (PyErr_ExceptionMatches(PyExc_AttributeError)) { }
PyErr_Clear(); else if (prep == NULL) {
ns = PyDict_New(); ns = PyDict_New();
}
else {
Py_DECREF(meta);
Py_XDECREF(mkw);
Py_DECREF(bases);
return NULL;
}
} }
else { else {
PyObject *pargs[2] = {name, bases}; PyObject *pargs[2] = {name, bases};
@ -1127,8 +1118,7 @@ builtin_getattr(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
return NULL; return NULL;
} }
if (dflt != NULL) { if (dflt != NULL) {
result = _PyObject_GetAttrWithoutError(v, name); if (_PyObject_LookupAttr(v, name, &result) == 0) {
if (result == NULL && !PyErr_Occurred()) {
Py_INCREF(dflt); Py_INCREF(dflt);
return dflt; return dflt;
} }
@ -1191,13 +1181,12 @@ builtin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name)
"hasattr(): attribute name must be string"); "hasattr(): attribute name must be string");
return NULL; return NULL;
} }
v = _PyObject_GetAttrWithoutError(obj, name); if (_PyObject_LookupAttr(obj, name, &v) < 0) {
if (v == NULL) {
if (!PyErr_Occurred()) {
Py_RETURN_FALSE;
}
return NULL; return NULL;
} }
if (v == NULL) {
Py_RETURN_FALSE;
}
Py_DECREF(v); Py_DECREF(v);
Py_RETURN_TRUE; Py_RETURN_TRUE;
} }

View File

@ -4813,13 +4813,12 @@ import_from(PyObject *v, PyObject *name)
_Py_IDENTIFIER(__name__); _Py_IDENTIFIER(__name__);
PyObject *fullmodname, *pkgname, *pkgpath, *pkgname_or_unknown, *errmsg; PyObject *fullmodname, *pkgname, *pkgpath, *pkgname_or_unknown, *errmsg;
x = PyObject_GetAttr(v, name); if (_PyObject_LookupAttr(v, name, &x) != 0) {
if (x != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError))
return x; return x;
}
/* Issue #17636: in case this failed because of a circular relative /* Issue #17636: in case this failed because of a circular relative
import, try to fallback on reading the module directly from import, try to fallback on reading the module directly from
sys.modules. */ sys.modules. */
PyErr_Clear();
pkgname = _PyObject_GetAttrId(v, &PyId___name__); pkgname = _PyObject_GetAttrId(v, &PyId___name__);
if (pkgname == NULL) { if (pkgname == NULL) {
goto error; goto error;
@ -4881,21 +4880,20 @@ import_all_from(PyObject *locals, PyObject *v)
{ {
_Py_IDENTIFIER(__all__); _Py_IDENTIFIER(__all__);
_Py_IDENTIFIER(__dict__); _Py_IDENTIFIER(__dict__);
PyObject *all = _PyObject_GetAttrId(v, &PyId___all__); PyObject *all, *dict, *name, *value;
PyObject *dict, *name, *value;
int skip_leading_underscores = 0; int skip_leading_underscores = 0;
int pos, err; int pos, err;
if (_PyObject_LookupAttrId(v, &PyId___all__, &all) < 0) {
return -1; /* Unexpected error */
}
if (all == NULL) { if (all == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) if (_PyObject_LookupAttrId(v, &PyId___dict__, &dict) < 0) {
return -1; /* Unexpected error */ return -1;
PyErr_Clear(); }
dict = _PyObject_GetAttrId(v, &PyId___dict__);
if (dict == NULL) { if (dict == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return -1;
PyErr_SetString(PyExc_ImportError, PyErr_SetString(PyExc_ImportError,
"from-import-* object has no __dict__ and no __all__"); "from-import-* object has no __dict__ and no __all__");
return -1; return -1;
} }
all = PyMapping_Keys(dict); all = PyMapping_Keys(dict);

View File

@ -540,15 +540,11 @@ PyObject * _PyCodec_LookupTextEncoding(const char *encoding,
* attribute. * attribute.
*/ */
if (!PyTuple_CheckExact(codec)) { if (!PyTuple_CheckExact(codec)) {
attr = _PyObject_GetAttrId(codec, &PyId__is_text_encoding); if (_PyObject_LookupAttrId(codec, &PyId__is_text_encoding, &attr) < 0) {
if (attr == NULL) { Py_DECREF(codec);
if (PyErr_ExceptionMatches(PyExc_AttributeError)) { return NULL;
PyErr_Clear(); }
} else { if (attr != NULL) {
Py_DECREF(codec);
return NULL;
}
} else {
is_text_codec = PyObject_IsTrue(attr); is_text_codec = PyObject_IsTrue(attr);
Py_DECREF(attr); Py_DECREF(attr);
if (is_text_codec <= 0) { if (is_text_codec <= 0) {