mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									2b822a0bb1
								
							
						
					
					
						commit
						f320be77ff
					
				
					 22 changed files with 1455 additions and 1442 deletions
				
			
		|  | @ -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 *); | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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"); | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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. */ | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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__, ©func) < 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) { | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -497,11 +497,27 @@ def isSimpleType(self, field): | ||||||
| 
 | 
 | ||||||
|     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 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): | ||||||
|             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 @@ def visitModule(self, mod): | ||||||
|     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 @@ def visitModule(self, mod): | ||||||
| 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 @@ def visitModule(self, mod): | ||||||
|     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) | ||||||
|  |  | ||||||
							
								
								
									
										2218
									
								
								Python/Python-ast.c
									
										
									
									
									
								
							
							
						
						
									
										2218
									
								
								Python/Python-ast.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -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. */ | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Serhiy Storchaka
						Serhiy Storchaka