PyObject * Base_getattro(PyObject *obj, PyObject *name) { /* This is a modified copy of PyObject_GenericGetAttr. See the change note below. */ PyTypeObject *tp = obj->ob_type; PyObject *descr = NULL; PyObject *res = NULL; descrgetfunc f; long dictoffset; PyObject **dictptr; if (!PyString_Check(name)){ #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name and we wouldn't want to break those. */ if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (name == NULL) return NULL; } else #endif { PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return NULL; } } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } #if !defined(Py_TPFLAGS_HAVE_VERSION_TAG) /* Inline _PyType_Lookup */ /* this is not quite _PyType_Lookup anymore */ { int i, n; PyObject *mro, *base, *dict; /* Look in tp_dict of types in MRO */ mro = tp->tp_mro; assert(mro != NULL); assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(mro, i); if (PyClass_Check(base)) dict = ((PyClassObject *)base)->cl_dict; else { assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; } assert(dict && PyDict_Check(dict)); descr = PyDict_GetItem(dict, name); if (descr != NULL) break; } } #else descr = _PyType_Lookup(tp, name); #endif Py_XINCREF(descr); f = NULL; if (descr != NULL && PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) { f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } } /* Inline _PyObject_GetDictPtr */ dictoffset = tp->tp_dictoffset; if (dictoffset != 0) { PyObject *dict; if (dictoffset < 0) { int tsize; size_t size; tsize = ((PyVarObject *)obj)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(tp, tsize); dictoffset += (long)size; assert(dictoffset > 0); assert(dictoffset % SIZEOF_VOID_P == 0); } dictptr = (PyObject **) ((char *)obj + dictoffset); dict = *dictptr; if (dict != NULL) { Py_INCREF(dict); res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); Py_XDECREF(descr); Py_DECREF(dict); /* CHANGED! If the tp_descr_get of res is of_get, then call it. */ if ((strcmp(PyString_AsString(name), "__parent__") != 0) && PyObject_TypeCheck(res->ob_type, &ExtensionClassType) && res->ob_type->tp_descr_get != NULL) { PyObject *tres; tres = res->ob_type->tp_descr_get( res, obj, OBJECT(obj->ob_type)); Py_DECREF(res); res = tres; } goto done; } Py_DECREF(dict); } } if (f != NULL) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } if (descr != NULL) { res = descr; /* descr was already increfed above */ goto done; } /* CHANGED: Just use the name. Don't format. */ PyErr_SetObject(PyExc_AttributeError, name); done: Py_DECREF(name); return res; }
PyObject *LOOKUP_ATTRIBUTE_CLASS_SLOT(PyObject *source) { CHECK_OBJECT(source); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = _PyType_Lookup(type, const_str_plain___class__); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); #if PYTHON_VERSION < 300 if (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)) { #endif func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 300 } #endif } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = PyDict_GetItem(dict, const_str_plain___class__); if (result != NULL) { Py_INCREF(result); Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } #if PYTHON_VERSION < 300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyInstanceObject *source_instance = (PyInstanceObject *)source; PyObject *result = (PyObject *)source_instance->in_class; Py_INCREF(result); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, const_str_plain___class__); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)"__class__"); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } }
int PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) { PyTypeObject *tp = obj->ob_type; PyObject *descr; descrsetfunc f; PyObject **dictptr; int res = -1; #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name and we wouldn't want to break those. */ if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (name == NULL) return -1; } else #endif if (!PyString_Check(name)){ PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return -1; } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } descr = _PyType_Lookup(tp, name); f = NULL; if (descr != NULL) { f = descr->ob_type->tp_descr_set; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, value); goto done; } } dictptr = _PyObject_GetDictPtr(obj); if (dictptr != NULL) { PyObject *dict = *dictptr; if (dict == NULL && value != NULL) { dict = PyDict_New(); if (dict == NULL) goto done; *dictptr = dict; } if (dict != NULL) { if (value == NULL) res = PyDict_DelItem(dict, name); else res = PyDict_SetItem(dict, name, value); if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_SetObject(PyExc_AttributeError, name); goto done; } } if (f != NULL) { res = f(descr, obj, value); goto done; } if (descr == NULL) { PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", tp->tp_name, PyString_AS_STRING(name)); goto done; } PyErr_Format(PyExc_AttributeError, "'%.50s' object attribute '%.400s' is read-only", tp->tp_name, PyString_AS_STRING(name)); done: Py_DECREF(name); return res; }
PyObject *LOOKUP_ATTRIBUTE(PyObject *source, PyObject *attr_name) { /* Note: There are 2 specializations of this function, that need to be * updated in line with this: LOOKUP_ATTRIBUTE_[DICT|CLASS]_SLOT */ CHECK_OBJECT(source); CHECK_OBJECT(attr_name); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = _PyType_Lookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); #if PYTHON_VERSION < 300 if (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)) { #endif func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 300 } #endif } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = PyDict_GetItem(dict, attr_name); if (result != NULL) { Py_INCREF(result); Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } #if PYTHON_VERSION < 300 PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyObject *result = LOOKUP_INSTANCE(source, attr_name); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, attr_name); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } }
PyObject * PyObject_GenericGetAttr(PyObject *obj, PyObject *name) { PyTypeObject *tp = obj->ob_type; PyObject *descr = NULL; PyObject *res = NULL; descrgetfunc f; Py_ssize_t dictoffset; PyObject **dictptr; if (!PyString_Check(name)){ #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name and we wouldn't want to break those. */ if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (name == NULL) return NULL; } else #endif { PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); return NULL; } } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } /* Inline _PyType_Lookup */ { Py_ssize_t i, n; PyObject *mro, *base, *dict; /* Look in tp_dict of types in MRO */ mro = tp->tp_mro; assert(mro != NULL); assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(mro, i); if (PyClass_Check(base)) dict = ((PyClassObject *)base)->cl_dict; else { assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; } assert(dict && PyDict_Check(dict)); descr = PyDict_GetItem(dict, name); if (descr != NULL) break; } } Py_XINCREF(descr); f = NULL; if (descr != NULL && PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) { f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } } /* Inline _PyObject_GetDictPtr */ dictoffset = tp->tp_dictoffset; if (dictoffset != 0) { PyObject *dict; if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)obj)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(tp, tsize); dictoffset += (long)size; assert(dictoffset > 0); assert(dictoffset % SIZEOF_VOID_P == 0); } dictptr = (PyObject **) ((char *)obj + dictoffset); dict = *dictptr; if (dict != NULL) { res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); Py_XDECREF(descr); goto done; } } } if (f != NULL) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } if (descr != NULL) { res = descr; /* descr was already increfed above */ goto done; } PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", tp->tp_name, PyString_AS_STRING(name)); done: Py_DECREF(name); return res; }