diff options
Diffstat (limited to 'Objects/object.c')
-rw-r--r-- | Objects/object.c | 110 |
1 files changed, 99 insertions, 11 deletions
diff --git a/Objects/object.c b/Objects/object.c index d88ae3b94f..5da6cffdb9 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -477,7 +477,7 @@ PyObject_Repr(PyObject *v) #ifdef Py_DEBUG /* PyObject_Repr() must not be called with an exception set, - because it may clear it (directly or indirectly) and so the + because it can clear it (directly or indirectly) and so the caller loses its exception */ assert(!PyErr_Occurred()); #endif @@ -526,7 +526,7 @@ PyObject_Str(PyObject *v) #ifdef Py_DEBUG /* PyObject_Str() must not be called with an exception set, - because it may clear it (directly or indirectly) and so the + because it can clear it (directly or indirectly) and so the caller loses its exception */ assert(!PyErr_Occurred()); #endif @@ -596,7 +596,7 @@ PyObject_Bytes(PyObject *v) func = _PyObject_LookupSpecial(v, &PyId___bytes__); if (func != NULL) { - result = PyObject_CallFunctionObjArgs(func, NULL); + result = _PyObject_CallNoArg(func); Py_DECREF(func); if (result == NULL) return NULL; @@ -890,10 +890,10 @@ PyObject_GetAttr(PyObject *v, PyObject *name) if (tp->tp_getattro != NULL) return (*tp->tp_getattro)(v, name); if (tp->tp_getattr != NULL) { - char *name_str = PyUnicode_AsUTF8(name); + const char *name_str = PyUnicode_AsUTF8(name); if (name_str == NULL) return NULL; - return (*tp->tp_getattr)(v, name_str); + return (*tp->tp_getattr)(v, (char *)name_str); } PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%U'", @@ -934,10 +934,10 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value) return err; } if (tp->tp_setattr != NULL) { - char *name_str = PyUnicode_AsUTF8(name); + const char *name_str = PyUnicode_AsUTF8(name); if (name_str == NULL) return -1; - err = (*tp->tp_setattr)(v, name_str, value); + err = (*tp->tp_setattr)(v, (char *)name_str, value); Py_DECREF(name); return err; } @@ -1025,11 +1025,99 @@ _PyObject_NextNotImplemented(PyObject *self) return NULL; } -/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */ + +/* Specialized version of _PyObject_GenericGetAttrWithDict + specifically for the LOAD_METHOD opcode. + + Return 1 if a method is found, 0 if it's a regular attribute + from __dict__ or something returned by using a descriptor + protocol. + + `method` will point to the resolved attribute or NULL. In the + latter case, an error will be set. +*/ +int +_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) +{ + PyTypeObject *tp = Py_TYPE(obj); + PyObject *descr; + descrgetfunc f = NULL; + PyObject **dictptr, *dict; + PyObject *attr; + int meth_found = 0; + + assert(*method == NULL); + + if (Py_TYPE(obj)->tp_getattro != PyObject_GenericGetAttr + || !PyUnicode_Check(name)) { + *method = PyObject_GetAttr(obj, name); + return 0; + } + + if (tp->tp_dict == NULL && PyType_Ready(tp) < 0) + return 0; + + descr = _PyType_Lookup(tp, name); + if (descr != NULL) { + Py_INCREF(descr); + if (PyFunction_Check(descr) || + (Py_TYPE(descr) == &PyMethodDescr_Type)) { + meth_found = 1; + } else { + f = descr->ob_type->tp_descr_get; + if (f != NULL && PyDescr_IsData(descr)) { + *method = f(descr, obj, (PyObject *)obj->ob_type); + Py_DECREF(descr); + return 0; + } + } + } + + dictptr = _PyObject_GetDictPtr(obj); + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); + attr = PyDict_GetItem(dict, name); + if (attr != NULL) { + Py_INCREF(attr); + *method = attr; + Py_DECREF(dict); + Py_XDECREF(descr); + return 0; + } + Py_DECREF(dict); + } + + if (meth_found) { + *method = descr; + return 1; + } + + if (f != NULL) { + *method = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + return 0; + } + + if (descr != NULL) { + *method = descr; + return 0; + } + + PyErr_Format(PyExc_AttributeError, + "'%.50s' object has no attribute '%U'", + tp->tp_name, name); + return 0; +} + +/* Generic GetAttr functions - put these in your tp_[gs]etattro slot. */ PyObject * _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) { + /* Make sure the logic of _PyObject_GetMethod is in sync with + this method. + */ + PyTypeObject *tp = Py_TYPE(obj); PyObject *descr = NULL; PyObject *res = NULL; @@ -1314,7 +1402,7 @@ _dir_object(PyObject *obj) return NULL; } /* use __dir__ */ - result = PyObject_CallFunctionObjArgs(dirfunc, NULL); + result = _PyObject_CallNoArg(dirfunc); Py_DECREF(dirfunc); if (result == NULL) return NULL; @@ -1366,7 +1454,7 @@ none_dealloc(PyObject* ignore) static PyObject * none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { - if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) { + if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) { PyErr_SetString(PyExc_TypeError, "NoneType takes no arguments"); return NULL; } @@ -1485,7 +1573,7 @@ static PyMethodDef notimplemented_methods[] = { static PyObject * notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { - if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) { + if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) { PyErr_SetString(PyExc_TypeError, "NotImplementedType takes no arguments"); return NULL; } |